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 ILGenerator ig = ec.ig;
1363 EmitLong (ig, Value);
1366 static public void EmitLong (ILGenerator ig, long l)
1368 if ((l >> 32) == 0){
1369 IntLiteral.EmitInt (ig, unchecked ((int) l));
1370 ig.Emit (OpCodes.Conv_U8);
1372 ig.Emit (OpCodes.Ldc_I8, l);
1376 public override string AsString ()
1378 return Value.ToString ();
1381 public override object GetValue ()
1386 public override DoubleConstant ConvertToDouble ()
1388 return new DoubleConstant (Value, loc);
1391 public override FloatConstant ConvertToFloat ()
1393 return new FloatConstant (Value, loc);
1396 public override ULongConstant ConvertToULong ()
1401 return new ULongConstant ((ulong) Value, loc);
1404 public override LongConstant ConvertToLong ()
1409 public override UIntConstant ConvertToUInt ()
1414 public override IntConstant ConvertToInt ()
1419 public override Constant Increment ()
1421 return new LongConstant (checked(Value + 1), loc);
1424 public override bool IsDefaultValue {
1430 public override bool IsNegative {
1436 public override bool IsZeroInteger {
1437 get { return Value == 0; }
1440 public override Constant Reduce (bool inCheckedContext, Type target_type)
1442 if (target_type == TypeManager.byte_type) {
1443 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1444 return new ByteConstant ((byte) Value, Location);
1446 if (target_type == TypeManager.sbyte_type) {
1447 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1448 return new SByteConstant ((sbyte) Value, Location);
1450 if (target_type == TypeManager.short_type) {
1451 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1452 return new ShortConstant ((short) Value, Location);
1454 if (target_type == TypeManager.ushort_type) {
1455 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1456 return new UShortConstant ((ushort) Value, Location);
1458 if (target_type == TypeManager.int32_type) {
1459 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1460 return new IntConstant ((int) Value, Location);
1462 if (target_type == TypeManager.uint32_type) {
1463 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1464 return new UIntConstant ((uint) Value, Location);
1466 if (target_type == TypeManager.uint64_type) {
1467 CheckUnsigned (inCheckedContext, Value);
1468 return new ULongConstant ((ulong) Value, Location);
1470 if (target_type == TypeManager.float_type)
1471 return new FloatConstant ((float) Value, Location);
1472 if (target_type == TypeManager.double_type)
1473 return new DoubleConstant ((double) Value, Location);
1474 if (target_type == TypeManager.char_type) {
1475 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1476 return new CharConstant ((char) Value, Location);
1478 if (target_type == TypeManager.decimal_type)
1479 return new DecimalConstant ((decimal) Value, Location);
1486 public class ULongConstant : IntegralConstant {
1487 public readonly ulong Value;
1489 public ULongConstant (ulong v, Location loc):
1492 type = TypeManager.uint64_type;
1493 eclass = ExprClass.Value;
1497 public override void Emit (EmitContext ec)
1499 ILGenerator ig = ec.ig;
1501 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1504 public override string AsString ()
1506 return Value.ToString ();
1509 public override object GetValue ()
1514 public override DoubleConstant ConvertToDouble ()
1516 return new DoubleConstant (Value, loc);
1519 public override FloatConstant ConvertToFloat ()
1521 return new FloatConstant (Value, loc);
1524 public override ULongConstant ConvertToULong ()
1529 public override LongConstant ConvertToLong ()
1534 public override UIntConstant ConvertToUInt ()
1539 public override IntConstant ConvertToInt ()
1544 public override Constant Increment ()
1546 return new ULongConstant (checked(Value + 1), loc);
1549 public override bool IsDefaultValue {
1555 public override bool IsNegative {
1561 public override bool IsZeroInteger {
1562 get { return Value == 0; }
1565 public override Constant Reduce (bool inCheckedContext, Type target_type)
1567 if (target_type == TypeManager.byte_type) {
1568 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1569 return new ByteConstant ((byte) Value, Location);
1571 if (target_type == TypeManager.sbyte_type) {
1572 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1573 return new SByteConstant ((sbyte) Value, Location);
1575 if (target_type == TypeManager.short_type) {
1576 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1577 return new ShortConstant ((short) Value, Location);
1579 if (target_type == TypeManager.ushort_type) {
1580 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1581 return new UShortConstant ((ushort) Value, Location);
1583 if (target_type == TypeManager.int32_type) {
1584 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1585 return new IntConstant ((int) Value, Location);
1587 if (target_type == TypeManager.uint32_type) {
1588 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1589 return new UIntConstant ((uint) Value, Location);
1591 if (target_type == TypeManager.int64_type) {
1592 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1593 return new LongConstant ((long) Value, Location);
1595 if (target_type == TypeManager.float_type)
1596 return new FloatConstant ((float) Value, Location);
1597 if (target_type == TypeManager.double_type)
1598 return new DoubleConstant ((double) Value, Location);
1599 if (target_type == TypeManager.char_type) {
1600 CheckRange (inCheckedContext, Value, Char.MaxValue);
1601 return new CharConstant ((char) Value, Location);
1603 if (target_type == TypeManager.decimal_type)
1604 return new DecimalConstant ((decimal) Value, Location);
1611 public class FloatConstant : Constant {
1612 public readonly float Value;
1614 public FloatConstant (float v, Location loc):
1617 type = TypeManager.float_type;
1618 eclass = ExprClass.Value;
1622 public override void Emit (EmitContext ec)
1624 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1627 public override string AsString ()
1629 return Value.ToString ();
1632 public override object GetValue ()
1637 public override DoubleConstant ConvertToDouble ()
1639 return new DoubleConstant (Value, loc);
1642 public override FloatConstant ConvertToFloat ()
1647 public override LongConstant ConvertToLong ()
1652 public override UIntConstant ConvertToUInt ()
1657 public override IntConstant ConvertToInt ()
1662 public override Constant Increment ()
1664 return new FloatConstant (checked(Value + 1), loc);
1667 public override bool IsDefaultValue {
1673 public override bool IsNegative {
1679 public override Constant Reduce (bool inCheckedContext, Type target_type)
1681 if (target_type == TypeManager.byte_type) {
1682 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1683 return new ByteConstant ((byte) Value, Location);
1685 if (target_type == TypeManager.sbyte_type) {
1686 CheckRange (inCheckedContext, Value, sbyte.MinValue, sbyte.MaxValue);
1687 return new SByteConstant ((sbyte) Value, Location);
1689 if (target_type == TypeManager.short_type) {
1690 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1691 return new ShortConstant ((short) Value, Location);
1693 if (target_type == TypeManager.ushort_type) {
1694 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1695 return new UShortConstant ((ushort) Value, Location);
1697 if (target_type == TypeManager.int32_type) {
1698 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1699 return new IntConstant ((int) Value, Location);
1701 if (target_type == TypeManager.uint32_type) {
1702 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1703 return new UIntConstant ((uint) Value, Location);
1705 if (target_type == TypeManager.int64_type) {
1706 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1707 return new LongConstant ((long) Value, Location);
1709 if (target_type == TypeManager.uint64_type) {
1710 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1711 return new ULongConstant ((ulong) Value, Location);
1713 if (target_type == TypeManager.double_type)
1714 return new DoubleConstant ((double) Value, Location);
1715 if (target_type == TypeManager.char_type) {
1716 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1717 return new CharConstant ((char) Value, Location);
1719 if (target_type == TypeManager.decimal_type)
1720 return new DecimalConstant ((decimal) Value, Location);
1727 public class DoubleConstant : Constant {
1728 public readonly double Value;
1730 public DoubleConstant (double v, Location loc):
1733 type = TypeManager.double_type;
1734 eclass = ExprClass.Value;
1738 public override void Emit (EmitContext ec)
1740 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1743 public override string AsString ()
1745 return Value.ToString ();
1748 public override object GetValue ()
1753 public override DoubleConstant ConvertToDouble ()
1758 public override FloatConstant ConvertToFloat ()
1763 public override ULongConstant ConvertToULong ()
1768 public override LongConstant ConvertToLong ()
1773 public override UIntConstant ConvertToUInt ()
1778 public override IntConstant ConvertToInt ()
1783 public override Constant Increment ()
1785 return new DoubleConstant (checked(Value + 1), loc);
1788 public override bool IsDefaultValue {
1794 public override bool IsNegative {
1800 public override Constant Reduce (bool inCheckedContext, Type target_type)
1802 if (target_type == TypeManager.byte_type) {
1803 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1804 return new ByteConstant ((byte) Value, Location);
1806 if (target_type == TypeManager.sbyte_type) {
1807 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1808 return new SByteConstant ((sbyte) Value, Location);
1810 if (target_type == TypeManager.short_type) {
1811 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1812 return new ShortConstant ((short) Value, Location);
1814 if (target_type == TypeManager.ushort_type) {
1815 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1816 return new UShortConstant ((ushort) Value, Location);
1818 if (target_type == TypeManager.int32_type) {
1819 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1820 return new IntConstant ((int) Value, Location);
1822 if (target_type == TypeManager.uint32_type) {
1823 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1824 return new UIntConstant ((uint) Value, Location);
1826 if (target_type == TypeManager.int64_type) {
1827 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1828 return new LongConstant ((long) Value, Location);
1830 if (target_type == TypeManager.uint64_type) {
1831 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1832 return new ULongConstant ((ulong) Value, Location);
1834 if (target_type == TypeManager.float_type)
1835 return new FloatConstant ((float) Value, Location);
1836 if (target_type == TypeManager.char_type) {
1837 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1838 return new CharConstant ((char) Value, Location);
1840 if (target_type == TypeManager.decimal_type)
1841 return new DecimalConstant ((decimal) Value, Location);
1848 public class DecimalConstant : Constant {
1849 public readonly decimal Value;
1851 public DecimalConstant (decimal d, Location loc):
1854 type = TypeManager.decimal_type;
1855 eclass = ExprClass.Value;
1859 override public string AsString ()
1861 return Value.ToString ();
1864 public override object GetValue ()
1866 return (object) Value;
1869 public override void Emit (EmitContext ec)
1871 ILGenerator ig = ec.ig;
1873 int [] words = Decimal.GetBits (Value);
1874 int power = (words [3] >> 16) & 0xff;
1876 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1878 IntConstant.EmitInt (ig, (int)Value);
1879 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1885 // FIXME: we could optimize this, and call a better
1889 IntConstant.EmitInt (ig, words [0]);
1890 IntConstant.EmitInt (ig, words [1]);
1891 IntConstant.EmitInt (ig, words [2]);
1894 IntConstant.EmitInt (ig, words [3] >> 31);
1897 IntConstant.EmitInt (ig, power);
1899 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1902 public override Constant Increment ()
1904 return new DecimalConstant (checked (Value + 1), loc);
1907 public override bool IsDefaultValue {
1913 public override bool IsNegative {
1919 public override Constant Reduce (bool inCheckedContext, Type target_type)
1921 if (target_type == TypeManager.sbyte_type)
1922 return new SByteConstant ((sbyte)Value, loc);
1923 if (target_type == TypeManager.byte_type)
1924 return new ByteConstant ((byte)Value, loc);
1925 if (target_type == TypeManager.short_type)
1926 return new ShortConstant ((short)Value, loc);
1927 if (target_type == TypeManager.ushort_type)
1928 return new UShortConstant ((ushort)Value, loc);
1929 if (target_type == TypeManager.int32_type)
1930 return new IntConstant ((int)Value, loc);
1931 if (target_type == TypeManager.uint32_type)
1932 return new UIntConstant ((uint)Value, loc);
1933 if (target_type == TypeManager.int64_type)
1934 return new LongConstant ((long)Value, loc);
1935 if (target_type == TypeManager.uint64_type)
1936 return new ULongConstant ((ulong)Value, loc);
1937 if (target_type == TypeManager.char_type)
1938 return new CharConstant ((char)Value, loc);
1939 if (target_type == TypeManager.float_type)
1940 return new FloatConstant ((float)Value, loc);
1941 if (target_type == TypeManager.double_type)
1942 return new DoubleConstant ((double)Value, loc);
1949 public class StringConstant : Constant {
1950 public readonly string Value;
1952 public StringConstant (string s, Location loc):
1955 type = TypeManager.string_type;
1956 eclass = ExprClass.Value;
1960 // FIXME: Escape the string.
1961 override public string AsString ()
1963 return "\"" + Value + "\"";
1966 public override object GetValue ()
1971 public override void Emit (EmitContext ec)
1974 ec.ig.Emit (OpCodes.Ldnull);
1976 ec.ig.Emit (OpCodes.Ldstr, Value);
1979 public override Constant Increment ()
1981 throw new NotSupportedException ();
1984 public override bool IsDefaultValue {
1986 return Value == null;
1990 public override bool IsNegative {
1996 public override Constant Reduce (bool inCheckedContext, Type target_type)