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 ();
239 protected static void CheckUnsigned (bool inCheckedContext, long value)
241 if (!inCheckedContext)
245 throw new OverflowException ();
249 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
250 /// It throws OverflowException
252 public abstract Constant Reduce (bool inCheckedContext, Type target_type);
255 /// Attempts to do a compile-time folding of a constant cast.
257 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
260 return TryReduce (ec, target_type);
262 catch (OverflowException) {
263 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
264 GetValue ().ToString (), TypeManager.CSharpName (target_type));
269 Constant TryReduce (EmitContext ec, Type target_type)
271 if (Type == target_type)
274 if (TypeManager.IsEnumType (target_type)) {
275 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
279 return new EnumConstant (c, target_type);
282 return Reduce (ec.ConstantCheckState, target_type);
286 public virtual DecimalConstant ConvertToDecimal ()
291 public virtual DoubleConstant ConvertToDouble ()
296 public virtual FloatConstant ConvertToFloat ()
301 public virtual ULongConstant ConvertToULong ()
306 public virtual LongConstant ConvertToLong ()
311 public virtual UIntConstant ConvertToUInt ()
316 public virtual IntConstant ConvertToInt ()
321 public abstract Constant Increment ();
323 public abstract bool IsDefaultValue {
327 public abstract bool IsNegative {
332 // Returns true iff 1) the stack type of this is one of Object,
333 // int32, int64 and 2) this == 0 or this == null.
335 public virtual bool IsZeroInteger {
336 get { return false; }
340 public abstract class IntegralConstant : Constant {
341 protected IntegralConstant (Location loc) :
346 public override void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
349 Reduce (true, target);
350 base.Error_ValueCannotBeConverted (loc, target, expl);
354 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
355 GetValue ().ToString (), TypeManager.CSharpName (target));
360 public class BoolConstant : Constant {
361 public readonly bool Value;
363 public BoolConstant (bool val, Location loc):
366 type = TypeManager.bool_type;
367 eclass = ExprClass.Value;
372 override public string AsString ()
374 return Value ? "true" : "false";
377 public override object GetValue ()
379 return (object) Value;
383 public override void Emit (EmitContext ec)
386 ec.ig.Emit (OpCodes.Ldc_I4_1);
388 ec.ig.Emit (OpCodes.Ldc_I4_0);
391 public override Constant Increment ()
393 throw new NotSupportedException ();
396 public override bool IsDefaultValue {
402 public override bool IsNegative {
408 public override bool IsZeroInteger {
409 get { return Value == false; }
412 public override Constant Reduce (bool inCheckedContext, Type target_type)
419 public class ByteConstant : IntegralConstant {
420 public readonly byte Value;
422 public ByteConstant (byte v, Location loc):
425 type = TypeManager.byte_type;
426 eclass = ExprClass.Value;
430 public override void Emit (EmitContext ec)
432 IntLiteral.EmitInt (ec.ig, Value);
435 public override string AsString ()
437 return Value.ToString ();
440 public override object GetValue ()
445 public override DoubleConstant ConvertToDouble ()
447 return new DoubleConstant (Value, loc);
450 public override FloatConstant ConvertToFloat ()
452 return new FloatConstant (Value, loc);
455 public override ULongConstant ConvertToULong ()
457 return new ULongConstant (Value, loc);
460 public override LongConstant ConvertToLong ()
462 return new LongConstant (Value, loc);
465 public override UIntConstant ConvertToUInt ()
467 return new UIntConstant (Value, loc);
470 public override IntConstant ConvertToInt ()
472 return new IntConstant (Value, loc);
475 public override Constant Increment ()
477 return new ByteConstant (checked ((byte)(Value + 1)), loc);
480 public override bool IsDefaultValue {
486 public override bool IsNegative {
492 public override bool IsZeroInteger {
493 get { return Value == 0; }
496 public override Constant Reduce (bool inCheckedContext, Type target_type)
498 if (target_type == TypeManager.sbyte_type) {
499 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
500 return new SByteConstant ((sbyte) Value, Location);
502 if (target_type == TypeManager.short_type)
503 return new ShortConstant ((short) Value, Location);
504 if (target_type == TypeManager.ushort_type)
505 return new UShortConstant ((ushort) Value, Location);
506 if (target_type == TypeManager.int32_type)
507 return new IntConstant ((int) Value, Location);
508 if (target_type == TypeManager.uint32_type)
509 return new UIntConstant ((uint) Value, Location);
510 if (target_type == TypeManager.int64_type)
511 return new LongConstant ((long) Value, Location);
512 if (target_type == TypeManager.uint64_type)
513 return new ULongConstant ((ulong) Value, Location);
514 if (target_type == TypeManager.float_type)
515 return new FloatConstant ((float) Value, Location);
516 if (target_type == TypeManager.double_type)
517 return new DoubleConstant ((double) Value, Location);
518 if (target_type == TypeManager.char_type)
519 return new CharConstant ((char) Value, Location);
520 if (target_type == TypeManager.decimal_type)
521 return new DecimalConstant ((decimal) Value, Location);
528 public class CharConstant : Constant {
529 public readonly char Value;
531 public CharConstant (char v, Location loc):
534 type = TypeManager.char_type;
535 eclass = ExprClass.Value;
539 public override void Emit (EmitContext ec)
541 IntLiteral.EmitInt (ec.ig, Value);
544 static public string descape (char c)
570 return c.ToString ();
573 public override string AsString ()
575 return "\"" + descape (Value) + "\"";
578 public override object GetValue ()
583 public override DoubleConstant ConvertToDouble ()
585 return new DoubleConstant (Value, loc);
588 public override FloatConstant ConvertToFloat ()
590 return new FloatConstant (Value, loc);
593 public override ULongConstant ConvertToULong ()
595 return new ULongConstant (Value, loc);
598 public override LongConstant ConvertToLong ()
600 return new LongConstant (Value, loc);
603 public override UIntConstant ConvertToUInt ()
605 return new UIntConstant (Value, loc);
608 public override IntConstant ConvertToInt ()
610 return new IntConstant (Value, loc);
613 public override Constant Increment ()
615 return new CharConstant (checked ((char)(Value + 1)), loc);
618 public override bool IsDefaultValue {
624 public override bool IsNegative {
630 public override bool IsZeroInteger {
631 get { return Value == '\0'; }
634 public override Constant Reduce (bool inCheckedContext, Type target_type)
636 if (target_type == TypeManager.byte_type) {
637 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
638 return new ByteConstant ((byte) Value, Location);
640 if (target_type == TypeManager.sbyte_type) {
641 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
642 return new SByteConstant ((sbyte) Value, Location);
644 if (target_type == TypeManager.short_type) {
645 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
646 return new ShortConstant ((short) Value, Location);
648 if (target_type == TypeManager.int32_type)
649 return new IntConstant ((int) Value, Location);
650 if (target_type == TypeManager.uint32_type)
651 return new UIntConstant ((uint) Value, Location);
652 if (target_type == TypeManager.int64_type)
653 return new LongConstant ((long) Value, Location);
654 if (target_type == TypeManager.uint64_type)
655 return new ULongConstant ((ulong) Value, Location);
656 if (target_type == TypeManager.float_type)
657 return new FloatConstant ((float) Value, Location);
658 if (target_type == TypeManager.double_type)
659 return new DoubleConstant ((double) Value, Location);
660 if (target_type == TypeManager.decimal_type)
661 return new DecimalConstant ((decimal) Value, Location);
668 public class SByteConstant : IntegralConstant {
669 public readonly sbyte Value;
671 public SByteConstant (sbyte v, Location loc):
674 type = TypeManager.sbyte_type;
675 eclass = ExprClass.Value;
679 public override void Emit (EmitContext ec)
681 IntLiteral.EmitInt (ec.ig, Value);
684 public override string AsString ()
686 return Value.ToString ();
689 public override object GetValue ()
694 public override DoubleConstant ConvertToDouble ()
696 return new DoubleConstant (Value, loc);
699 public override FloatConstant ConvertToFloat ()
701 return new FloatConstant (Value, loc);
704 public override ULongConstant ConvertToULong ()
707 return new ULongConstant ((ulong) Value, loc);
712 public override LongConstant ConvertToLong ()
714 return new LongConstant (Value, loc);
717 public override UIntConstant ConvertToUInt ()
722 public override IntConstant ConvertToInt ()
724 return new IntConstant (Value, loc);
727 public override Constant Increment ()
729 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
732 public override bool IsDefaultValue {
738 public override bool IsNegative {
744 public override bool IsZeroInteger {
745 get { return Value == 0; }
748 public override Constant Reduce (bool inCheckedContext, Type target_type)
750 if (target_type == TypeManager.byte_type) {
751 CheckUnsigned (inCheckedContext, Value);
752 return new ByteConstant ((byte) Value, Location);
754 if (target_type == TypeManager.short_type)
755 return new ShortConstant ((short) Value, Location);
756 if (target_type == TypeManager.ushort_type) {
757 CheckUnsigned (inCheckedContext, Value);
758 return new UShortConstant ((ushort) Value, Location);
759 } if (target_type == TypeManager.int32_type)
760 return new IntConstant ((int) Value, Location);
761 if (target_type == TypeManager.uint32_type) {
762 CheckUnsigned (inCheckedContext, Value);
763 return new UIntConstant ((uint) Value, Location);
764 } if (target_type == TypeManager.int64_type)
765 return new LongConstant ((long) Value, Location);
766 if (target_type == TypeManager.uint64_type) {
767 CheckUnsigned (inCheckedContext, Value);
768 return new ULongConstant ((ulong) Value, Location);
770 if (target_type == TypeManager.float_type)
771 return new FloatConstant ((float) Value, Location);
772 if (target_type == TypeManager.double_type)
773 return new DoubleConstant ((double) Value, Location);
774 if (target_type == TypeManager.char_type) {
775 CheckUnsigned (inCheckedContext, Value);
776 return new CharConstant ((char) Value, Location);
778 if (target_type == TypeManager.decimal_type)
779 return new DecimalConstant ((decimal) Value, Location);
786 public class ShortConstant : IntegralConstant {
787 public readonly short Value;
789 public ShortConstant (short v, Location loc):
792 type = TypeManager.short_type;
793 eclass = ExprClass.Value;
797 public override void Emit (EmitContext ec)
799 IntLiteral.EmitInt (ec.ig, Value);
802 public override string AsString ()
804 return Value.ToString ();
807 public override object GetValue ()
812 public override DoubleConstant ConvertToDouble ()
814 return new DoubleConstant (Value, loc);
817 public override FloatConstant ConvertToFloat ()
819 return new FloatConstant (Value, loc);
822 public override ULongConstant ConvertToULong ()
827 public override LongConstant ConvertToLong ()
829 return new LongConstant (Value, loc);
832 public override UIntConstant ConvertToUInt ()
837 public override IntConstant ConvertToInt ()
839 return new IntConstant (Value, loc);
842 public override Constant Increment ()
844 return new ShortConstant (checked((short)(Value + 1)), loc);
847 public override bool IsDefaultValue {
853 public override bool IsZeroInteger {
854 get { return Value == 0; }
857 public override bool IsNegative {
863 public override Constant Reduce (bool inCheckedContext, Type target_type)
865 if (target_type == TypeManager.byte_type) {
866 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
867 return new ByteConstant ((byte) Value, Location);
869 if (target_type == TypeManager.sbyte_type) {
870 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
871 return new SByteConstant ((sbyte) Value, Location);
873 if (target_type == TypeManager.ushort_type) {
874 CheckUnsigned (inCheckedContext, Value);
875 return new UShortConstant ((ushort) Value, Location);
877 if (target_type == TypeManager.int32_type)
878 return new IntConstant ((int) Value, Location);
879 if (target_type == TypeManager.uint32_type) {
880 CheckUnsigned (inCheckedContext, Value);
881 return new UIntConstant ((uint) Value, Location);
883 if (target_type == TypeManager.int64_type)
884 return new LongConstant ((long) Value, Location);
885 if (target_type == TypeManager.uint64_type) {
886 CheckUnsigned (inCheckedContext, Value);
887 return new ULongConstant ((ulong) Value, Location);
889 if (target_type == TypeManager.float_type)
890 return new FloatConstant ((float) Value, Location);
891 if (target_type == TypeManager.double_type)
892 return new DoubleConstant ((double) Value, Location);
893 if (target_type == TypeManager.char_type) {
894 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
895 return new CharConstant ((char) Value, Location);
897 if (target_type == TypeManager.decimal_type)
898 return new DecimalConstant ((decimal) Value, Location);
905 public class UShortConstant : IntegralConstant {
906 public readonly ushort Value;
908 public UShortConstant (ushort v, Location loc):
911 type = TypeManager.ushort_type;
912 eclass = ExprClass.Value;
916 public override void Emit (EmitContext ec)
918 IntLiteral.EmitInt (ec.ig, Value);
921 public override string AsString ()
923 return Value.ToString ();
926 public override object GetValue ()
931 public override DoubleConstant ConvertToDouble ()
933 return new DoubleConstant (Value, loc);
936 public override FloatConstant ConvertToFloat ()
938 return new FloatConstant (Value, loc);
941 public override ULongConstant ConvertToULong ()
943 return new ULongConstant (Value, loc);
946 public override LongConstant ConvertToLong ()
948 return new LongConstant (Value, loc);
951 public override UIntConstant ConvertToUInt ()
953 return new UIntConstant (Value, loc);
956 public override IntConstant ConvertToInt ()
958 return new IntConstant (Value, loc);
961 public override Constant Increment ()
963 return new UShortConstant (checked((ushort)(Value + 1)), loc);
966 public override bool IsDefaultValue {
972 public override bool IsNegative {
978 public override bool IsZeroInteger {
979 get { return Value == 0; }
982 public override Constant Reduce (bool inCheckedContext, Type target_type)
984 if (target_type == TypeManager.byte_type) {
985 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
986 return new ByteConstant ((byte) Value, Location);
988 if (target_type == TypeManager.sbyte_type) {
989 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
990 return new SByteConstant ((sbyte) Value, Location);
992 if (target_type == TypeManager.short_type) {
993 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
994 return new ShortConstant ((short) Value, Location);
996 if (target_type == TypeManager.int32_type)
997 return new IntConstant ((int) Value, Location);
998 if (target_type == TypeManager.uint32_type)
999 return new UIntConstant ((uint) Value, Location);
1000 if (target_type == TypeManager.int64_type)
1001 return new LongConstant ((long) Value, Location);
1002 if (target_type == TypeManager.uint64_type)
1003 return new ULongConstant ((ulong) Value, Location);
1004 if (target_type == TypeManager.float_type)
1005 return new FloatConstant ((float) Value, Location);
1006 if (target_type == TypeManager.double_type)
1007 return new DoubleConstant ((double) Value, Location);
1008 if (target_type == TypeManager.char_type) {
1009 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1010 return new CharConstant ((char) Value, Location);
1012 if (target_type == TypeManager.decimal_type)
1013 return new DecimalConstant ((decimal) Value, Location);
1019 public class IntConstant : IntegralConstant {
1020 public readonly int Value;
1022 public IntConstant (int v, Location loc):
1025 type = TypeManager.int32_type;
1026 eclass = ExprClass.Value;
1030 static public void EmitInt (ILGenerator ig, int i)
1034 ig.Emit (OpCodes.Ldc_I4_M1);
1038 ig.Emit (OpCodes.Ldc_I4_0);
1042 ig.Emit (OpCodes.Ldc_I4_1);
1046 ig.Emit (OpCodes.Ldc_I4_2);
1050 ig.Emit (OpCodes.Ldc_I4_3);
1054 ig.Emit (OpCodes.Ldc_I4_4);
1058 ig.Emit (OpCodes.Ldc_I4_5);
1062 ig.Emit (OpCodes.Ldc_I4_6);
1066 ig.Emit (OpCodes.Ldc_I4_7);
1070 ig.Emit (OpCodes.Ldc_I4_8);
1074 if (i >= -128 && i <= 127){
1075 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
1077 ig.Emit (OpCodes.Ldc_I4, i);
1082 public override void Emit (EmitContext ec)
1084 EmitInt (ec.ig, Value);
1087 public override string AsString ()
1089 return Value.ToString ();
1092 public override object GetValue ()
1097 public override DecimalConstant ConvertToDecimal()
1099 return new DecimalConstant (Value, loc);
1102 public override DoubleConstant ConvertToDouble ()
1104 return new DoubleConstant (Value, loc);
1107 public override FloatConstant ConvertToFloat ()
1109 return new FloatConstant (Value, loc);
1112 public override ULongConstant ConvertToULong ()
1117 return new ULongConstant ((ulong) Value, loc);
1120 public override LongConstant ConvertToLong ()
1122 return new LongConstant (Value, loc);
1125 public override UIntConstant ConvertToUInt ()
1130 return new UIntConstant ((uint) Value, loc);
1133 public override IntConstant ConvertToInt ()
1138 public override Constant Increment ()
1140 return new IntConstant (checked(Value + 1), loc);
1143 public override bool IsDefaultValue {
1149 public override bool IsNegative {
1155 public override bool IsZeroInteger {
1156 get { return Value == 0; }
1159 public override Constant Reduce (bool inCheckedContext, Type target_type)
1161 if (target_type == TypeManager.byte_type) {
1162 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1163 return new ByteConstant ((byte) Value, Location);
1165 if (target_type == TypeManager.sbyte_type) {
1166 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1167 return new SByteConstant ((sbyte) Value, Location);
1169 if (target_type == TypeManager.short_type) {
1170 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1171 return new ShortConstant ((short) Value, Location);
1173 if (target_type == TypeManager.ushort_type) {
1174 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1175 return new UShortConstant ((ushort) Value, Location);
1177 if (target_type == TypeManager.uint32_type) {
1178 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1179 return new UIntConstant ((uint) Value, Location);
1181 if (target_type == TypeManager.int64_type)
1182 return new LongConstant ((long) Value, Location);
1183 if (target_type == TypeManager.uint64_type) {
1184 CheckUnsigned (inCheckedContext, Value);
1185 return new ULongConstant ((ulong) Value, Location);
1187 if (target_type == TypeManager.float_type)
1188 return new FloatConstant ((float) Value, Location);
1189 if (target_type == TypeManager.double_type)
1190 return new DoubleConstant ((double) Value, Location);
1191 if (target_type == TypeManager.char_type) {
1192 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1193 return new CharConstant ((char) Value, Location);
1195 if (target_type == TypeManager.decimal_type)
1196 return new DecimalConstant ((decimal) Value, Location);
1202 public class UIntConstant : IntegralConstant {
1203 public readonly uint Value;
1205 public UIntConstant (uint v, Location loc):
1208 type = TypeManager.uint32_type;
1209 eclass = ExprClass.Value;
1213 public override void Emit (EmitContext ec)
1215 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1218 public override string AsString ()
1220 return Value.ToString ();
1223 public override object GetValue ()
1228 public override DoubleConstant ConvertToDouble ()
1230 return new DoubleConstant (Value, loc);
1233 public override FloatConstant ConvertToFloat ()
1235 return new FloatConstant (Value, loc);
1238 public override ULongConstant ConvertToULong ()
1240 return new ULongConstant (Value, loc);
1243 public override LongConstant ConvertToLong ()
1245 return new LongConstant (Value, loc);
1248 public override UIntConstant ConvertToUInt ()
1253 public override IntConstant ConvertToInt ()
1258 public override Constant Increment ()
1260 return new UIntConstant (checked(Value + 1), loc);
1263 public override bool IsDefaultValue {
1269 public override bool IsNegative {
1275 public override bool IsZeroInteger {
1276 get { return Value == 0; }
1279 public override Constant Reduce (bool inCheckedContext, Type target_type)
1281 if (target_type == TypeManager.byte_type) {
1282 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1283 return new ByteConstant ((byte) Value, Location);
1285 if (target_type == TypeManager.sbyte_type) {
1286 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1287 return new SByteConstant ((sbyte) Value, Location);
1289 if (target_type == TypeManager.short_type) {
1290 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1291 return new ShortConstant ((short) Value, Location);
1293 if (target_type == TypeManager.ushort_type) {
1294 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1295 return new UShortConstant ((ushort) Value, Location);
1297 if (target_type == TypeManager.int32_type) {
1298 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1299 return new IntConstant ((int) Value, Location);
1301 if (target_type == TypeManager.int64_type)
1302 return new LongConstant ((long) Value, Location);
1303 if (target_type == TypeManager.uint64_type)
1304 return new ULongConstant ((ulong) Value, Location);
1305 if (target_type == TypeManager.float_type)
1306 return new FloatConstant ((float) Value, Location);
1307 if (target_type == TypeManager.double_type)
1308 return new DoubleConstant ((double) Value, Location);
1309 if (target_type == TypeManager.char_type) {
1310 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1311 return new CharConstant ((char) Value, Location);
1313 if (target_type == TypeManager.decimal_type)
1314 return new DecimalConstant ((decimal) Value, Location);
1321 public class LongConstant : IntegralConstant {
1322 public readonly long Value;
1324 public LongConstant (long v, Location loc):
1327 type = TypeManager.int64_type;
1328 eclass = ExprClass.Value;
1332 public override void Emit (EmitContext ec)
1334 ILGenerator ig = ec.ig;
1336 EmitLong (ig, Value);
1339 static public void EmitLong (ILGenerator ig, long l)
1341 if ((l >> 32) == 0){
1342 IntLiteral.EmitInt (ig, unchecked ((int) l));
1343 ig.Emit (OpCodes.Conv_U8);
1345 ig.Emit (OpCodes.Ldc_I8, l);
1349 public override string AsString ()
1351 return Value.ToString ();
1354 public override object GetValue ()
1359 public override DoubleConstant ConvertToDouble ()
1361 return new DoubleConstant (Value, loc);
1364 public override FloatConstant ConvertToFloat ()
1366 return new FloatConstant (Value, loc);
1369 public override ULongConstant ConvertToULong ()
1374 return new ULongConstant ((ulong) Value, loc);
1377 public override LongConstant ConvertToLong ()
1382 public override UIntConstant ConvertToUInt ()
1387 public override IntConstant ConvertToInt ()
1392 public override Constant Increment ()
1394 return new LongConstant (checked(Value + 1), loc);
1397 public override bool IsDefaultValue {
1403 public override bool IsNegative {
1409 public override bool IsZeroInteger {
1410 get { return Value == 0; }
1413 public override Constant Reduce (bool inCheckedContext, Type target_type)
1415 if (target_type == TypeManager.byte_type) {
1416 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1417 return new ByteConstant ((byte) Value, Location);
1419 if (target_type == TypeManager.sbyte_type) {
1420 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1421 return new SByteConstant ((sbyte) Value, Location);
1423 if (target_type == TypeManager.short_type) {
1424 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1425 return new ShortConstant ((short) Value, Location);
1427 if (target_type == TypeManager.ushort_type) {
1428 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1429 return new UShortConstant ((ushort) Value, Location);
1431 if (target_type == TypeManager.int32_type) {
1432 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1433 return new IntConstant ((int) Value, Location);
1435 if (target_type == TypeManager.uint32_type) {
1436 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1437 return new UIntConstant ((uint) Value, Location);
1439 if (target_type == TypeManager.uint64_type) {
1440 CheckUnsigned (inCheckedContext, Value);
1441 return new ULongConstant ((ulong) Value, Location);
1443 if (target_type == TypeManager.float_type)
1444 return new FloatConstant ((float) Value, Location);
1445 if (target_type == TypeManager.double_type)
1446 return new DoubleConstant ((double) Value, Location);
1447 if (target_type == TypeManager.char_type) {
1448 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1449 return new CharConstant ((char) Value, Location);
1451 if (target_type == TypeManager.decimal_type)
1452 return new DecimalConstant ((decimal) Value, Location);
1459 public class ULongConstant : IntegralConstant {
1460 public readonly ulong Value;
1462 public ULongConstant (ulong v, Location loc):
1465 type = TypeManager.uint64_type;
1466 eclass = ExprClass.Value;
1470 public override void Emit (EmitContext ec)
1472 ILGenerator ig = ec.ig;
1474 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1477 public override string AsString ()
1479 return Value.ToString ();
1482 public override object GetValue ()
1487 public override DoubleConstant ConvertToDouble ()
1489 return new DoubleConstant (Value, loc);
1492 public override FloatConstant ConvertToFloat ()
1494 return new FloatConstant (Value, loc);
1497 public override ULongConstant ConvertToULong ()
1502 public override LongConstant ConvertToLong ()
1507 public override UIntConstant ConvertToUInt ()
1512 public override IntConstant ConvertToInt ()
1517 public override Constant Increment ()
1519 return new ULongConstant (checked(Value + 1), loc);
1522 public override bool IsDefaultValue {
1528 public override bool IsNegative {
1534 public override bool IsZeroInteger {
1535 get { return Value == 0; }
1538 public override Constant Reduce (bool inCheckedContext, Type target_type)
1540 if (target_type == TypeManager.byte_type) {
1541 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1542 return new ByteConstant ((byte) Value, Location);
1544 if (target_type == TypeManager.sbyte_type) {
1545 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1546 return new SByteConstant ((sbyte) Value, Location);
1548 if (target_type == TypeManager.short_type) {
1549 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1550 return new ShortConstant ((short) Value, Location);
1552 if (target_type == TypeManager.ushort_type) {
1553 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1554 return new UShortConstant ((ushort) Value, Location);
1556 if (target_type == TypeManager.int32_type) {
1557 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1558 return new IntConstant ((int) Value, Location);
1560 if (target_type == TypeManager.uint32_type) {
1561 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1562 return new UIntConstant ((uint) Value, Location);
1564 if (target_type == TypeManager.int64_type) {
1565 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1566 return new LongConstant ((long) Value, Location);
1568 if (target_type == TypeManager.float_type)
1569 return new FloatConstant ((float) Value, Location);
1570 if (target_type == TypeManager.double_type)
1571 return new DoubleConstant ((double) Value, Location);
1572 if (target_type == TypeManager.char_type) {
1573 CheckRange (inCheckedContext, Value, Char.MaxValue);
1574 return new CharConstant ((char) Value, Location);
1576 if (target_type == TypeManager.decimal_type)
1577 return new DecimalConstant ((decimal) Value, Location);
1584 public class FloatConstant : Constant {
1585 public readonly float Value;
1587 public FloatConstant (float v, Location loc):
1590 type = TypeManager.float_type;
1591 eclass = ExprClass.Value;
1595 public override void Emit (EmitContext ec)
1597 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1600 public override string AsString ()
1602 return Value.ToString ();
1605 public override object GetValue ()
1610 public override DoubleConstant ConvertToDouble ()
1612 return new DoubleConstant (Value, loc);
1615 public override FloatConstant ConvertToFloat ()
1620 public override LongConstant ConvertToLong ()
1625 public override UIntConstant ConvertToUInt ()
1630 public override IntConstant ConvertToInt ()
1635 public override Constant Increment ()
1637 return new FloatConstant (checked(Value + 1), loc);
1640 public override bool IsDefaultValue {
1646 public override bool IsNegative {
1652 public override Constant Reduce (bool inCheckedContext, Type target_type)
1654 if (target_type == TypeManager.byte_type)
1655 return new ByteConstant ((byte) Value, Location);
1656 if (target_type == TypeManager.sbyte_type)
1657 return new SByteConstant ((sbyte) Value, Location);
1658 if (target_type == TypeManager.short_type)
1659 return new ShortConstant ((short) Value, Location);
1660 if (target_type == TypeManager.ushort_type)
1661 return new UShortConstant ((ushort) Value, Location);
1662 if (target_type == TypeManager.int32_type)
1663 return new IntConstant ((int) Value, Location);
1664 if (target_type == TypeManager.uint32_type)
1665 return new UIntConstant ((uint) Value, Location);
1666 if (target_type == TypeManager.int64_type)
1667 return new LongConstant ((long) Value, Location);
1668 if (target_type == TypeManager.uint64_type)
1669 return new ULongConstant ((ulong) Value, Location);
1670 if (target_type == TypeManager.double_type)
1671 return new DoubleConstant ((double) Value, Location);
1672 if (target_type == TypeManager.char_type)
1673 return new CharConstant ((char) Value, Location);
1674 if (target_type == TypeManager.decimal_type)
1675 return new DecimalConstant ((decimal) Value, Location);
1682 public class DoubleConstant : Constant {
1683 public readonly double Value;
1685 public DoubleConstant (double v, Location loc):
1688 type = TypeManager.double_type;
1689 eclass = ExprClass.Value;
1693 public override void Emit (EmitContext ec)
1695 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1698 public override string AsString ()
1700 return Value.ToString ();
1703 public override object GetValue ()
1708 public override DoubleConstant ConvertToDouble ()
1713 public override FloatConstant ConvertToFloat ()
1718 public override ULongConstant ConvertToULong ()
1723 public override LongConstant ConvertToLong ()
1728 public override UIntConstant ConvertToUInt ()
1733 public override IntConstant ConvertToInt ()
1738 public override Constant Increment ()
1740 return new DoubleConstant (checked(Value + 1), loc);
1743 public override bool IsDefaultValue {
1749 public override bool IsNegative {
1755 public override Constant Reduce (bool inCheckedContext, Type target_type)
1757 if (target_type == TypeManager.byte_type) {
1758 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1759 return new ByteConstant ((byte) Value, Location);
1761 if (target_type == TypeManager.sbyte_type) {
1762 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1763 return new SByteConstant ((sbyte) Value, Location);
1765 if (target_type == TypeManager.short_type)
1766 return new ShortConstant ((short) Value, Location);
1767 if (target_type == TypeManager.ushort_type)
1768 return new UShortConstant ((ushort) Value, Location);
1769 if (target_type == TypeManager.int32_type)
1770 return new IntConstant ((int) Value, Location);
1771 if (target_type == TypeManager.uint32_type)
1772 return new UIntConstant ((uint) Value, Location);
1773 if (target_type == TypeManager.int64_type)
1774 return new LongConstant ((long) Value, Location);
1775 if (target_type == TypeManager.uint64_type)
1776 return new ULongConstant ((ulong) Value, Location);
1777 if (target_type == TypeManager.float_type)
1778 return new FloatConstant ((float) Value, Location);
1779 if (target_type == TypeManager.char_type) {
1780 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1781 return new CharConstant ((char) Value, Location);
1783 if (target_type == TypeManager.decimal_type)
1784 return new DecimalConstant ((decimal) Value, Location);
1791 public class DecimalConstant : Constant {
1792 public readonly decimal Value;
1794 public DecimalConstant (decimal d, Location loc):
1797 type = TypeManager.decimal_type;
1798 eclass = ExprClass.Value;
1802 override public string AsString ()
1804 return Value.ToString ();
1807 public override object GetValue ()
1809 return (object) Value;
1812 public override void Emit (EmitContext ec)
1814 ILGenerator ig = ec.ig;
1816 int [] words = Decimal.GetBits (Value);
1817 int power = (words [3] >> 16) & 0xff;
1819 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1821 IntConstant.EmitInt (ig, (int)Value);
1822 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1828 // FIXME: we could optimize this, and call a better
1832 IntConstant.EmitInt (ig, words [0]);
1833 IntConstant.EmitInt (ig, words [1]);
1834 IntConstant.EmitInt (ig, words [2]);
1837 IntConstant.EmitInt (ig, words [3] >> 31);
1840 IntConstant.EmitInt (ig, power);
1842 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1845 public override Constant Increment ()
1847 return new DecimalConstant (checked (Value + 1), loc);
1850 public override bool IsDefaultValue {
1856 public override bool IsNegative {
1862 public override Constant Reduce (bool inCheckedContext, Type target_type)
1864 if (target_type == TypeManager.sbyte_type)
1865 return new SByteConstant ((sbyte)Value, loc);
1866 if (target_type == TypeManager.byte_type)
1867 return new ByteConstant ((byte)Value, loc);
1868 if (target_type == TypeManager.short_type)
1869 return new ShortConstant ((short)Value, loc);
1870 if (target_type == TypeManager.ushort_type)
1871 return new UShortConstant ((ushort)Value, loc);
1872 if (target_type == TypeManager.int32_type)
1873 return new IntConstant ((int)Value, loc);
1874 if (target_type == TypeManager.uint32_type)
1875 return new UIntConstant ((uint)Value, loc);
1876 if (target_type == TypeManager.int64_type)
1877 return new LongConstant ((long)Value, loc);
1878 if (target_type == TypeManager.uint64_type)
1879 return new ULongConstant ((ulong)Value, loc);
1880 if (target_type == TypeManager.char_type)
1881 return new CharConstant ((char)Value, loc);
1882 if (target_type == TypeManager.float_type)
1883 return new FloatConstant ((float)Value, loc);
1884 if (target_type == TypeManager.double_type)
1885 return new DoubleConstant ((double)Value, loc);
1892 public class StringConstant : Constant {
1893 public readonly string Value;
1895 public StringConstant (string s, Location loc):
1898 type = TypeManager.string_type;
1899 eclass = ExprClass.Value;
1903 // FIXME: Escape the string.
1904 override public string AsString ()
1906 return "\"" + Value + "\"";
1909 public override object GetValue ()
1914 public override void Emit (EmitContext ec)
1917 ec.ig.Emit (OpCodes.Ldnull);
1919 ec.ig.Emit (OpCodes.Ldstr, Value);
1922 public override Constant Increment ()
1924 throw new NotSupportedException ();
1927 public override bool IsDefaultValue {
1929 return Value == null;
1933 public override bool IsNegative {
1939 public override Constant Reduce (bool inCheckedContext, Type target_type)