2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2001 Ximian, Inc.
12 namespace Mono.CSharp {
15 using System.Reflection.Emit;
18 /// Base class for constants and literals.
20 public abstract class Constant : Expression {
22 protected Constant (Location loc)
28 /// This is different from ToString in that ToString
29 /// is supposed to be there for debugging purposes,
30 /// and is not guaranteed to be useful for anything else,
31 /// AsString() will provide something that can be used
32 /// for round-tripping C# code. Maybe it can be used
33 /// for IL assembly as well.
35 public abstract string AsString ();
37 override public string ToString ()
39 return this.GetType ().Name + " (" + AsString () + ")";
42 public override bool GetAttributableValue (Type valueType, out object value)
44 Constant c = ImplicitConversionRequired (valueType, loc);
50 value = c.GetTypedValue ();
55 /// This is used to obtain the actual value of the literal
56 /// cast into an object.
58 public abstract object GetValue ();
60 public virtual object GetTypedValue ()
66 /// Constants are always born in a fully resolved state
68 public override Expression DoResolve (EmitContext ec)
73 public Constant ImplicitConversionRequired (Type type, Location loc)
75 Constant c = ConvertImplicitly (type);
77 Error_ValueCannotBeConverted (null, loc, type, false);
81 public virtual Constant ConvertImplicitly (Type type)
83 if (this.type == type)
86 if (type == TypeManager.object_type)
87 return new EmptyConstantCast (this, type);
89 if (Convert.ImplicitNumericConversion (this, type) == null)
93 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
96 // We should always catch the error before this is ever
97 // reached, by calling Convert.ImplicitStandardConversionExists
100 String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
103 return CreateConstant (type, constant_value, loc);
106 /// Returns a constant instance based on Type
107 /// The returned value is already resolved.
108 public static Constant CreateConstant (Type t, object v, Location loc)
110 if (t == TypeManager.int32_type)
111 return new IntConstant ((int) v, loc);
112 if (t == TypeManager.string_type)
113 return new StringConstant ((string) v, loc);
114 if (t == TypeManager.uint32_type)
115 return new UIntConstant ((uint) v, loc);
116 if (t == TypeManager.int64_type)
117 return new LongConstant ((long) v, loc);
118 if (t == TypeManager.uint64_type)
119 return new ULongConstant ((ulong) v, loc);
120 if (t == TypeManager.float_type)
121 return new FloatConstant ((float) v, loc);
122 if (t == TypeManager.double_type)
123 return new DoubleConstant ((double) v, loc);
124 if (t == TypeManager.short_type)
125 return new ShortConstant ((short)v, loc);
126 if (t == TypeManager.ushort_type)
127 return new UShortConstant ((ushort)v, loc);
128 if (t == TypeManager.sbyte_type)
129 return new SByteConstant ((sbyte)v, loc);
130 if (t == TypeManager.byte_type)
131 return new ByteConstant ((byte)v, loc);
132 if (t == TypeManager.char_type)
133 return new CharConstant ((char)v, loc);
134 if (t == TypeManager.bool_type)
135 return new BoolConstant ((bool) v, loc);
136 if (t == TypeManager.decimal_type)
137 return new DecimalConstant ((decimal) v, loc);
138 if (TypeManager.IsEnumType (t)) {
139 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
141 real_type = System.Enum.GetUnderlyingType (real_type);
142 return new EnumConstant (CreateConstant (real_type, v, loc), t);
144 if (v == null && !TypeManager.IsValueType (t))
145 return new EmptyConstantCast (new NullConstant (loc), t);
147 throw new Exception ("Unknown type for constant (" + t +
151 protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
153 if (!inCheckedContext)
157 throw new OverflowException ();
160 protected static void CheckRange (bool inCheckedContext, double value, long min, long max)
162 if (!inCheckedContext)
165 if (((value < min) || (value > max)))
166 throw new OverflowException ();
168 if (double.IsNaN (value))
169 throw new OverflowException ();
172 protected static void CheckRange (bool inCheckedContext, double value, ulong min, ulong max)
174 if (!inCheckedContext)
177 if (((value < min) || (value > max)))
178 throw new OverflowException ();
180 if (double.IsNaN (value))
181 throw new OverflowException ();
184 protected static void CheckUnsigned (bool inCheckedContext, long value)
186 if (!inCheckedContext)
190 throw new OverflowException ();
194 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
195 /// It throws OverflowException
197 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
198 public abstract Constant ConvertExplicitly (bool inCheckedContext, Type target_type);
201 /// Attempts to do a compile-time folding of a constant cast.
203 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
206 return TryReduce (ec, target_type);
208 catch (OverflowException) {
209 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
210 GetValue ().ToString (), TypeManager.CSharpName (target_type));
215 Constant TryReduce (EmitContext ec, Type target_type)
217 if (Type == target_type)
220 if (TypeManager.IsEnumType (target_type)) {
221 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
225 return new EnumConstant (c, target_type);
228 return ConvertExplicitly (ec.ConstantCheckState, target_type);
231 public abstract Constant Increment ();
234 /// Need to pass type as the constant can require a boxing
235 /// and in such case no optimization is possible
237 public bool IsDefaultInitializer (Type type)
240 return IsDefaultValue;
242 return Type == TypeManager.null_type;
245 public abstract bool IsDefaultValue {
249 public abstract bool IsNegative {
254 // Returns true iff 1) the stack type of this is one of Object,
255 // int32, int64 and 2) this == 0 or this == null.
257 public virtual bool IsZeroInteger {
258 get { return false; }
262 public abstract class IntegralConstant : Constant {
263 protected IntegralConstant (Location loc) :
268 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
271 ConvertExplicitly (true, target);
272 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
276 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
277 GetValue ().ToString (), TypeManager.CSharpName (target));
282 public class BoolConstant : Constant {
283 public readonly bool Value;
285 public BoolConstant (bool val, Location loc):
288 type = TypeManager.bool_type;
289 eclass = ExprClass.Value;
294 override public string AsString ()
296 return Value ? "true" : "false";
299 public override object GetValue ()
301 return (object) Value;
305 public override void Emit (EmitContext ec)
308 ec.ig.Emit (OpCodes.Ldc_I4_1);
310 ec.ig.Emit (OpCodes.Ldc_I4_0);
313 public override Constant Increment ()
315 throw new NotSupportedException ();
318 public override bool IsDefaultValue {
324 public override bool IsNegative {
330 public override bool IsZeroInteger {
331 get { return Value == false; }
334 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
341 public class ByteConstant : IntegralConstant {
342 public readonly byte Value;
344 public ByteConstant (byte v, Location loc):
347 type = TypeManager.byte_type;
348 eclass = ExprClass.Value;
352 public override void Emit (EmitContext ec)
354 IntLiteral.EmitInt (ec.ig, Value);
357 public override string AsString ()
359 return Value.ToString ();
362 public override object GetValue ()
367 public override Constant Increment ()
369 return new ByteConstant (checked ((byte)(Value + 1)), loc);
372 public override bool IsDefaultValue {
378 public override bool IsNegative {
384 public override bool IsZeroInteger {
385 get { return Value == 0; }
388 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
390 if (target_type == TypeManager.sbyte_type) {
391 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
392 return new SByteConstant ((sbyte) Value, Location);
394 if (target_type == TypeManager.short_type)
395 return new ShortConstant ((short) Value, Location);
396 if (target_type == TypeManager.ushort_type)
397 return new UShortConstant ((ushort) Value, Location);
398 if (target_type == TypeManager.int32_type)
399 return new IntConstant ((int) Value, Location);
400 if (target_type == TypeManager.uint32_type)
401 return new UIntConstant ((uint) Value, Location);
402 if (target_type == TypeManager.int64_type)
403 return new LongConstant ((long) Value, Location);
404 if (target_type == TypeManager.uint64_type)
405 return new ULongConstant ((ulong) Value, Location);
406 if (target_type == TypeManager.float_type)
407 return new FloatConstant ((float) Value, Location);
408 if (target_type == TypeManager.double_type)
409 return new DoubleConstant ((double) Value, Location);
410 if (target_type == TypeManager.char_type)
411 return new CharConstant ((char) Value, Location);
412 if (target_type == TypeManager.decimal_type)
413 return new DecimalConstant ((decimal) Value, Location);
420 public class CharConstant : Constant {
421 public readonly char Value;
423 public CharConstant (char v, Location loc):
426 type = TypeManager.char_type;
427 eclass = ExprClass.Value;
431 public override void Emit (EmitContext ec)
433 IntLiteral.EmitInt (ec.ig, Value);
436 static public string descape (char c)
462 return c.ToString ();
465 public override string AsString ()
467 return "\"" + descape (Value) + "\"";
470 public override object GetValue ()
475 public override Constant Increment ()
477 return new CharConstant (checked ((char)(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 ConvertExplicitly (bool inCheckedContext, Type target_type)
498 if (target_type == TypeManager.byte_type) {
499 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
500 return new ByteConstant ((byte) Value, Location);
502 if (target_type == TypeManager.sbyte_type) {
503 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
504 return new SByteConstant ((sbyte) Value, Location);
506 if (target_type == TypeManager.short_type) {
507 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
508 return new ShortConstant ((short) Value, Location);
510 if (target_type == TypeManager.int32_type)
511 return new IntConstant ((int) Value, Location);
512 if (target_type == TypeManager.uint32_type)
513 return new UIntConstant ((uint) Value, Location);
514 if (target_type == TypeManager.int64_type)
515 return new LongConstant ((long) Value, Location);
516 if (target_type == TypeManager.uint64_type)
517 return new ULongConstant ((ulong) Value, Location);
518 if (target_type == TypeManager.float_type)
519 return new FloatConstant ((float) Value, Location);
520 if (target_type == TypeManager.double_type)
521 return new DoubleConstant ((double) Value, Location);
522 if (target_type == TypeManager.decimal_type)
523 return new DecimalConstant ((decimal) Value, Location);
530 public class SByteConstant : IntegralConstant {
531 public readonly sbyte Value;
533 public SByteConstant (sbyte v, Location loc):
536 type = TypeManager.sbyte_type;
537 eclass = ExprClass.Value;
541 public override void Emit (EmitContext ec)
543 IntLiteral.EmitInt (ec.ig, Value);
546 public override string AsString ()
548 return Value.ToString ();
551 public override object GetValue ()
556 public override Constant Increment ()
558 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
561 public override bool IsDefaultValue {
567 public override bool IsNegative {
573 public override bool IsZeroInteger {
574 get { return Value == 0; }
577 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
579 if (target_type == TypeManager.byte_type) {
580 CheckUnsigned (inCheckedContext, Value);
581 return new ByteConstant ((byte) Value, Location);
583 if (target_type == TypeManager.short_type)
584 return new ShortConstant ((short) Value, Location);
585 if (target_type == TypeManager.ushort_type) {
586 CheckUnsigned (inCheckedContext, Value);
587 return new UShortConstant ((ushort) Value, Location);
588 } if (target_type == TypeManager.int32_type)
589 return new IntConstant ((int) Value, Location);
590 if (target_type == TypeManager.uint32_type) {
591 CheckUnsigned (inCheckedContext, Value);
592 return new UIntConstant ((uint) Value, Location);
593 } if (target_type == TypeManager.int64_type)
594 return new LongConstant ((long) Value, Location);
595 if (target_type == TypeManager.uint64_type) {
596 CheckUnsigned (inCheckedContext, Value);
597 return new ULongConstant ((ulong) Value, Location);
599 if (target_type == TypeManager.float_type)
600 return new FloatConstant ((float) Value, Location);
601 if (target_type == TypeManager.double_type)
602 return new DoubleConstant ((double) Value, Location);
603 if (target_type == TypeManager.char_type) {
604 CheckUnsigned (inCheckedContext, Value);
605 return new CharConstant ((char) Value, Location);
607 if (target_type == TypeManager.decimal_type)
608 return new DecimalConstant ((decimal) Value, Location);
615 public class ShortConstant : IntegralConstant {
616 public readonly short Value;
618 public ShortConstant (short v, Location loc):
621 type = TypeManager.short_type;
622 eclass = ExprClass.Value;
626 public override void Emit (EmitContext ec)
628 IntLiteral.EmitInt (ec.ig, Value);
631 public override string AsString ()
633 return Value.ToString ();
636 public override object GetValue ()
641 public override Constant Increment ()
643 return new ShortConstant (checked((short)(Value + 1)), loc);
646 public override bool IsDefaultValue {
652 public override bool IsZeroInteger {
653 get { return Value == 0; }
656 public override bool IsNegative {
662 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
664 if (target_type == TypeManager.byte_type) {
665 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
666 return new ByteConstant ((byte) Value, Location);
668 if (target_type == TypeManager.sbyte_type) {
669 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
670 return new SByteConstant ((sbyte) Value, Location);
672 if (target_type == TypeManager.ushort_type) {
673 CheckUnsigned (inCheckedContext, Value);
674 return new UShortConstant ((ushort) Value, Location);
676 if (target_type == TypeManager.int32_type)
677 return new IntConstant ((int) Value, Location);
678 if (target_type == TypeManager.uint32_type) {
679 CheckUnsigned (inCheckedContext, Value);
680 return new UIntConstant ((uint) Value, Location);
682 if (target_type == TypeManager.int64_type)
683 return new LongConstant ((long) Value, Location);
684 if (target_type == TypeManager.uint64_type) {
685 CheckUnsigned (inCheckedContext, Value);
686 return new ULongConstant ((ulong) Value, Location);
688 if (target_type == TypeManager.float_type)
689 return new FloatConstant ((float) Value, Location);
690 if (target_type == TypeManager.double_type)
691 return new DoubleConstant ((double) Value, Location);
692 if (target_type == TypeManager.char_type) {
693 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
694 return new CharConstant ((char) Value, Location);
696 if (target_type == TypeManager.decimal_type)
697 return new DecimalConstant ((decimal) Value, Location);
704 public class UShortConstant : IntegralConstant {
705 public readonly ushort Value;
707 public UShortConstant (ushort v, Location loc):
710 type = TypeManager.ushort_type;
711 eclass = ExprClass.Value;
715 public override void Emit (EmitContext ec)
717 IntLiteral.EmitInt (ec.ig, Value);
720 public override string AsString ()
722 return Value.ToString ();
725 public override object GetValue ()
730 public override Constant Increment ()
732 return new UShortConstant (checked((ushort)(Value + 1)), loc);
735 public override bool IsDefaultValue {
741 public override bool IsNegative {
747 public override bool IsZeroInteger {
748 get { return Value == 0; }
751 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
753 if (target_type == TypeManager.byte_type) {
754 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
755 return new ByteConstant ((byte) Value, Location);
757 if (target_type == TypeManager.sbyte_type) {
758 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
759 return new SByteConstant ((sbyte) Value, Location);
761 if (target_type == TypeManager.short_type) {
762 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
763 return new ShortConstant ((short) Value, Location);
765 if (target_type == TypeManager.int32_type)
766 return new IntConstant ((int) Value, Location);
767 if (target_type == TypeManager.uint32_type)
768 return new UIntConstant ((uint) Value, Location);
769 if (target_type == TypeManager.int64_type)
770 return new LongConstant ((long) Value, Location);
771 if (target_type == TypeManager.uint64_type)
772 return new ULongConstant ((ulong) Value, Location);
773 if (target_type == TypeManager.float_type)
774 return new FloatConstant ((float) Value, Location);
775 if (target_type == TypeManager.double_type)
776 return new DoubleConstant ((double) Value, Location);
777 if (target_type == TypeManager.char_type) {
778 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
779 return new CharConstant ((char) Value, Location);
781 if (target_type == TypeManager.decimal_type)
782 return new DecimalConstant ((decimal) Value, Location);
788 public class IntConstant : IntegralConstant {
789 public readonly int Value;
791 public IntConstant (int v, Location loc):
794 type = TypeManager.int32_type;
795 eclass = ExprClass.Value;
799 static public void EmitInt (ILGenerator ig, int i)
803 ig.Emit (OpCodes.Ldc_I4_M1);
807 ig.Emit (OpCodes.Ldc_I4_0);
811 ig.Emit (OpCodes.Ldc_I4_1);
815 ig.Emit (OpCodes.Ldc_I4_2);
819 ig.Emit (OpCodes.Ldc_I4_3);
823 ig.Emit (OpCodes.Ldc_I4_4);
827 ig.Emit (OpCodes.Ldc_I4_5);
831 ig.Emit (OpCodes.Ldc_I4_6);
835 ig.Emit (OpCodes.Ldc_I4_7);
839 ig.Emit (OpCodes.Ldc_I4_8);
843 if (i >= -128 && i <= 127){
844 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
846 ig.Emit (OpCodes.Ldc_I4, i);
851 public override void Emit (EmitContext ec)
853 EmitInt (ec.ig, Value);
856 public override string AsString ()
858 return Value.ToString ();
861 public override object GetValue ()
866 public override Constant Increment ()
868 return new IntConstant (checked(Value + 1), loc);
871 public override bool IsDefaultValue {
877 public override bool IsNegative {
883 public override bool IsZeroInteger {
884 get { return Value == 0; }
887 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
889 if (target_type == TypeManager.byte_type) {
890 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
891 return new ByteConstant ((byte) Value, Location);
893 if (target_type == TypeManager.sbyte_type) {
894 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
895 return new SByteConstant ((sbyte) Value, Location);
897 if (target_type == TypeManager.short_type) {
898 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
899 return new ShortConstant ((short) Value, Location);
901 if (target_type == TypeManager.ushort_type) {
902 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
903 return new UShortConstant ((ushort) Value, Location);
905 if (target_type == TypeManager.uint32_type) {
906 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
907 return new UIntConstant ((uint) Value, Location);
909 if (target_type == TypeManager.int64_type)
910 return new LongConstant ((long) Value, Location);
911 if (target_type == TypeManager.uint64_type) {
912 CheckUnsigned (inCheckedContext, Value);
913 return new ULongConstant ((ulong) Value, Location);
915 if (target_type == TypeManager.float_type)
916 return new FloatConstant ((float) Value, Location);
917 if (target_type == TypeManager.double_type)
918 return new DoubleConstant ((double) Value, Location);
919 if (target_type == TypeManager.char_type) {
920 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
921 return new CharConstant ((char) Value, Location);
923 if (target_type == TypeManager.decimal_type)
924 return new DecimalConstant ((decimal) Value, Location);
930 public class UIntConstant : IntegralConstant {
931 public readonly uint Value;
933 public UIntConstant (uint v, Location loc):
936 type = TypeManager.uint32_type;
937 eclass = ExprClass.Value;
941 public override void Emit (EmitContext ec)
943 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
946 public override string AsString ()
948 return Value.ToString ();
951 public override object GetValue ()
956 public override Constant Increment ()
958 return new UIntConstant (checked(Value + 1), loc);
961 public override bool IsDefaultValue {
967 public override bool IsNegative {
973 public override bool IsZeroInteger {
974 get { return Value == 0; }
977 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
979 if (target_type == TypeManager.byte_type) {
980 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
981 return new ByteConstant ((byte) Value, Location);
983 if (target_type == TypeManager.sbyte_type) {
984 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
985 return new SByteConstant ((sbyte) Value, Location);
987 if (target_type == TypeManager.short_type) {
988 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
989 return new ShortConstant ((short) Value, Location);
991 if (target_type == TypeManager.ushort_type) {
992 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
993 return new UShortConstant ((ushort) Value, Location);
995 if (target_type == TypeManager.int32_type) {
996 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
997 return new IntConstant ((int) Value, Location);
999 if (target_type == TypeManager.int64_type)
1000 return new LongConstant ((long) Value, Location);
1001 if (target_type == TypeManager.uint64_type)
1002 return new ULongConstant ((ulong) Value, Location);
1003 if (target_type == TypeManager.float_type)
1004 return new FloatConstant ((float) Value, Location);
1005 if (target_type == TypeManager.double_type)
1006 return new DoubleConstant ((double) Value, Location);
1007 if (target_type == TypeManager.char_type) {
1008 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1009 return new CharConstant ((char) Value, Location);
1011 if (target_type == TypeManager.decimal_type)
1012 return new DecimalConstant ((decimal) Value, Location);
1019 public class LongConstant : IntegralConstant {
1020 public readonly long Value;
1022 public LongConstant (long v, Location loc):
1025 type = TypeManager.int64_type;
1026 eclass = ExprClass.Value;
1030 public override void Emit (EmitContext ec)
1032 EmitLong (ec.ig, Value);
1035 static public void EmitLong (ILGenerator ig, long l)
1037 if (l >= int.MinValue && l <= int.MaxValue) {
1038 IntLiteral.EmitInt (ig, unchecked ((int) l));
1039 ig.Emit (OpCodes.Conv_I8);
1042 ig.Emit (OpCodes.Ldc_I8, l);
1045 public override string AsString ()
1047 return Value.ToString ();
1050 public override object GetValue ()
1055 public override Constant Increment ()
1057 return new LongConstant (checked(Value + 1), loc);
1060 public override bool IsDefaultValue {
1066 public override bool IsNegative {
1072 public override bool IsZeroInteger {
1073 get { return Value == 0; }
1076 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1078 if (target_type == TypeManager.byte_type) {
1079 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1080 return new ByteConstant ((byte) Value, Location);
1082 if (target_type == TypeManager.sbyte_type) {
1083 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1084 return new SByteConstant ((sbyte) Value, Location);
1086 if (target_type == TypeManager.short_type) {
1087 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1088 return new ShortConstant ((short) Value, Location);
1090 if (target_type == TypeManager.ushort_type) {
1091 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1092 return new UShortConstant ((ushort) Value, Location);
1094 if (target_type == TypeManager.int32_type) {
1095 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1096 return new IntConstant ((int) Value, Location);
1098 if (target_type == TypeManager.uint32_type) {
1099 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1100 return new UIntConstant ((uint) Value, Location);
1102 if (target_type == TypeManager.uint64_type) {
1103 CheckUnsigned (inCheckedContext, Value);
1104 return new ULongConstant ((ulong) Value, Location);
1106 if (target_type == TypeManager.float_type)
1107 return new FloatConstant ((float) Value, Location);
1108 if (target_type == TypeManager.double_type)
1109 return new DoubleConstant ((double) Value, Location);
1110 if (target_type == TypeManager.char_type) {
1111 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1112 return new CharConstant ((char) Value, Location);
1114 if (target_type == TypeManager.decimal_type)
1115 return new DecimalConstant ((decimal) Value, Location);
1122 public class ULongConstant : IntegralConstant {
1123 public readonly ulong Value;
1125 public ULongConstant (ulong v, Location loc):
1128 type = TypeManager.uint64_type;
1129 eclass = ExprClass.Value;
1133 public override void Emit (EmitContext ec)
1135 ILGenerator ig = ec.ig;
1137 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1140 public override string AsString ()
1142 return Value.ToString ();
1145 public override object GetValue ()
1150 public override Constant Increment ()
1152 return new ULongConstant (checked(Value + 1), loc);
1155 public override bool IsDefaultValue {
1161 public override bool IsNegative {
1167 public override bool IsZeroInteger {
1168 get { return Value == 0; }
1171 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1173 if (target_type == TypeManager.byte_type) {
1174 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1175 return new ByteConstant ((byte) Value, Location);
1177 if (target_type == TypeManager.sbyte_type) {
1178 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1179 return new SByteConstant ((sbyte) Value, Location);
1181 if (target_type == TypeManager.short_type) {
1182 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1183 return new ShortConstant ((short) Value, Location);
1185 if (target_type == TypeManager.ushort_type) {
1186 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1187 return new UShortConstant ((ushort) Value, Location);
1189 if (target_type == TypeManager.int32_type) {
1190 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1191 return new IntConstant ((int) Value, Location);
1193 if (target_type == TypeManager.uint32_type) {
1194 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1195 return new UIntConstant ((uint) Value, Location);
1197 if (target_type == TypeManager.int64_type) {
1198 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1199 return new LongConstant ((long) Value, Location);
1201 if (target_type == TypeManager.float_type)
1202 return new FloatConstant ((float) Value, Location);
1203 if (target_type == TypeManager.double_type)
1204 return new DoubleConstant ((double) Value, Location);
1205 if (target_type == TypeManager.char_type) {
1206 CheckRange (inCheckedContext, Value, Char.MaxValue);
1207 return new CharConstant ((char) Value, Location);
1209 if (target_type == TypeManager.decimal_type)
1210 return new DecimalConstant ((decimal) Value, Location);
1217 public class FloatConstant : Constant {
1220 public FloatConstant (float v, Location loc):
1223 type = TypeManager.float_type;
1224 eclass = ExprClass.Value;
1228 public override void Emit (EmitContext ec)
1230 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1233 public override string AsString ()
1235 return Value.ToString ();
1238 public override object GetValue ()
1243 public override Constant Increment ()
1245 return new FloatConstant (checked(Value + 1), loc);
1248 public override bool IsDefaultValue {
1254 public override bool IsNegative {
1260 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1262 if (target_type == TypeManager.byte_type) {
1263 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1264 return new ByteConstant ((byte) Value, Location);
1266 if (target_type == TypeManager.sbyte_type) {
1267 CheckRange (inCheckedContext, Value, sbyte.MinValue, sbyte.MaxValue);
1268 return new SByteConstant ((sbyte) Value, Location);
1270 if (target_type == TypeManager.short_type) {
1271 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1272 return new ShortConstant ((short) Value, Location);
1274 if (target_type == TypeManager.ushort_type) {
1275 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1276 return new UShortConstant ((ushort) Value, Location);
1278 if (target_type == TypeManager.int32_type) {
1279 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1280 return new IntConstant ((int) Value, Location);
1282 if (target_type == TypeManager.uint32_type) {
1283 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1284 return new UIntConstant ((uint) Value, Location);
1286 if (target_type == TypeManager.int64_type) {
1287 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1288 return new LongConstant ((long) Value, Location);
1290 if (target_type == TypeManager.uint64_type) {
1291 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1292 return new ULongConstant ((ulong) Value, Location);
1294 if (target_type == TypeManager.double_type)
1295 return new DoubleConstant ((double) Value, Location);
1296 if (target_type == TypeManager.char_type) {
1297 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1298 return new CharConstant ((char) Value, Location);
1300 if (target_type == TypeManager.decimal_type)
1301 return new DecimalConstant ((decimal) Value, Location);
1308 public class DoubleConstant : Constant {
1309 public double Value;
1311 public DoubleConstant (double v, Location loc):
1314 type = TypeManager.double_type;
1315 eclass = ExprClass.Value;
1319 public override void Emit (EmitContext ec)
1321 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1324 public override string AsString ()
1326 return Value.ToString ();
1329 public override object GetValue ()
1334 public override Constant Increment ()
1336 return new DoubleConstant (checked(Value + 1), loc);
1339 public override bool IsDefaultValue {
1345 public override bool IsNegative {
1351 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1353 if (target_type == TypeManager.byte_type) {
1354 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1355 return new ByteConstant ((byte) Value, Location);
1357 if (target_type == TypeManager.sbyte_type) {
1358 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1359 return new SByteConstant ((sbyte) Value, Location);
1361 if (target_type == TypeManager.short_type) {
1362 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1363 return new ShortConstant ((short) Value, Location);
1365 if (target_type == TypeManager.ushort_type) {
1366 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1367 return new UShortConstant ((ushort) Value, Location);
1369 if (target_type == TypeManager.int32_type) {
1370 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1371 return new IntConstant ((int) Value, Location);
1373 if (target_type == TypeManager.uint32_type) {
1374 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1375 return new UIntConstant ((uint) Value, Location);
1377 if (target_type == TypeManager.int64_type) {
1378 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1379 return new LongConstant ((long) Value, Location);
1381 if (target_type == TypeManager.uint64_type) {
1382 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1383 return new ULongConstant ((ulong) Value, Location);
1385 if (target_type == TypeManager.float_type)
1386 return new FloatConstant ((float) Value, Location);
1387 if (target_type == TypeManager.char_type) {
1388 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1389 return new CharConstant ((char) Value, Location);
1391 if (target_type == TypeManager.decimal_type)
1392 return new DecimalConstant ((decimal) Value, Location);
1399 public class DecimalConstant : Constant {
1400 public readonly decimal Value;
1402 public DecimalConstant (decimal d, Location loc):
1405 type = TypeManager.decimal_type;
1406 eclass = ExprClass.Value;
1410 override public string AsString ()
1412 return Value.ToString ();
1415 public override object GetValue ()
1417 return (object) Value;
1420 public override void Emit (EmitContext ec)
1422 ILGenerator ig = ec.ig;
1424 int [] words = Decimal.GetBits (Value);
1425 int power = (words [3] >> 16) & 0xff;
1427 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1429 IntConstant.EmitInt (ig, (int)Value);
1430 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1436 // FIXME: we could optimize this, and call a better
1440 IntConstant.EmitInt (ig, words [0]);
1441 IntConstant.EmitInt (ig, words [1]);
1442 IntConstant.EmitInt (ig, words [2]);
1445 IntConstant.EmitInt (ig, words [3] >> 31);
1448 IntConstant.EmitInt (ig, power);
1450 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1453 public override Constant Increment ()
1455 return new DecimalConstant (checked (Value + 1), loc);
1458 public override bool IsDefaultValue {
1464 public override bool IsNegative {
1470 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1472 if (target_type == TypeManager.sbyte_type)
1473 return new SByteConstant ((sbyte)Value, loc);
1474 if (target_type == TypeManager.byte_type)
1475 return new ByteConstant ((byte)Value, loc);
1476 if (target_type == TypeManager.short_type)
1477 return new ShortConstant ((short)Value, loc);
1478 if (target_type == TypeManager.ushort_type)
1479 return new UShortConstant ((ushort)Value, loc);
1480 if (target_type == TypeManager.int32_type)
1481 return new IntConstant ((int)Value, loc);
1482 if (target_type == TypeManager.uint32_type)
1483 return new UIntConstant ((uint)Value, loc);
1484 if (target_type == TypeManager.int64_type)
1485 return new LongConstant ((long)Value, loc);
1486 if (target_type == TypeManager.uint64_type)
1487 return new ULongConstant ((ulong)Value, loc);
1488 if (target_type == TypeManager.char_type)
1489 return new CharConstant ((char)Value, loc);
1490 if (target_type == TypeManager.float_type)
1491 return new FloatConstant ((float)Value, loc);
1492 if (target_type == TypeManager.double_type)
1493 return new DoubleConstant ((double)Value, loc);
1500 public class StringConstant : Constant {
1501 public readonly string Value;
1503 public StringConstant (string s, Location loc):
1506 type = TypeManager.string_type;
1507 eclass = ExprClass.Value;
1511 // FIXME: Escape the string.
1512 override public string AsString ()
1514 return "\"" + Value + "\"";
1517 public override object GetValue ()
1522 public override void Emit (EmitContext ec)
1525 ec.ig.Emit (OpCodes.Ldnull);
1527 ec.ig.Emit (OpCodes.Ldstr, Value);
1530 public override Constant Increment ()
1532 throw new NotSupportedException ();
1535 public override bool IsDefaultValue {
1537 return Value == null;
1541 public override bool IsNegative {
1547 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)