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 if (valueType == TypeManager.object_type) {
45 value = GetTypedValue ();
49 Constant c = ImplicitConversionRequired (valueType, loc);
55 value = c.GetTypedValue ();
60 /// This is used to obtain the actual value of the literal
61 /// cast into an object.
63 public abstract object GetValue ();
65 public virtual object GetTypedValue ()
71 /// Constants are always born in a fully resolved state
73 public override Expression DoResolve (EmitContext ec)
78 public Constant ImplicitConversionRequired (Type type, Location loc)
80 Constant c = ConvertImplicitly (type);
82 Error_ValueCannotBeConverted (null, loc, type, false);
86 public virtual Constant ConvertImplicitly (Type type)
88 if (this.type == type)
91 if (Convert.ImplicitNumericConversion (this, type) == null)
95 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
98 // We should always catch the error before this is ever
99 // reached, by calling Convert.ImplicitStandardConversionExists
101 throw new Exception (
102 String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
105 return CreateConstant (type, constant_value, loc);
108 /// Returns a constant instance based on Type
109 /// The returned value is already resolved.
110 public static Constant CreateConstant (Type t, object v, Location loc)
112 if (t == TypeManager.int32_type)
113 return new IntConstant ((int) v, loc);
114 if (t == TypeManager.string_type)
115 return new StringConstant ((string) v, loc);
116 if (t == TypeManager.uint32_type)
117 return new UIntConstant ((uint) v, loc);
118 if (t == TypeManager.int64_type)
119 return new LongConstant ((long) v, loc);
120 if (t == TypeManager.uint64_type)
121 return new ULongConstant ((ulong) v, loc);
122 if (t == TypeManager.float_type)
123 return new FloatConstant ((float) v, loc);
124 if (t == TypeManager.double_type)
125 return new DoubleConstant ((double) v, loc);
126 if (t == TypeManager.short_type)
127 return new ShortConstant ((short)v, loc);
128 if (t == TypeManager.ushort_type)
129 return new UShortConstant ((ushort)v, loc);
130 if (t == TypeManager.sbyte_type)
131 return new SByteConstant ((sbyte)v, loc);
132 if (t == TypeManager.byte_type)
133 return new ByteConstant ((byte)v, loc);
134 if (t == TypeManager.char_type)
135 return new CharConstant ((char)v, loc);
136 if (t == TypeManager.bool_type)
137 return new BoolConstant ((bool) v, loc);
138 if (t == TypeManager.decimal_type)
139 return new DecimalConstant ((decimal) v, loc);
140 if (TypeManager.IsEnumType (t)) {
141 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
143 real_type = System.Enum.GetUnderlyingType (real_type);
144 return new EnumConstant (CreateConstant (real_type, v, loc), t);
146 if (v == null && !TypeManager.IsValueType (t))
147 return new EmptyConstantCast (new NullConstant (loc), t);
149 throw new Exception ("Unknown type for constant (" + t +
153 protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
155 if (!inCheckedContext)
159 throw new OverflowException ();
162 protected static void CheckRange (bool inCheckedContext, double value, long min, long max)
164 if (!inCheckedContext)
167 if (((value < min) || (value > max)))
168 throw new OverflowException ();
170 if (double.IsNaN (value))
171 throw new OverflowException ();
174 protected static void CheckRange (bool inCheckedContext, double value, ulong min, ulong max)
176 if (!inCheckedContext)
179 if (((value < min) || (value > max)))
180 throw new OverflowException ();
182 if (double.IsNaN (value))
183 throw new OverflowException ();
186 protected static void CheckUnsigned (bool inCheckedContext, long value)
188 if (!inCheckedContext)
192 throw new OverflowException ();
196 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
197 /// It throws OverflowException
199 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
200 public abstract Constant ConvertExplicitly (bool inCheckedContext, Type target_type);
203 /// Attempts to do a compile-time folding of a constant cast.
205 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
208 return TryReduce (ec, target_type);
210 catch (OverflowException) {
211 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
212 GetValue ().ToString (), TypeManager.CSharpName (target_type));
217 Constant TryReduce (EmitContext ec, Type target_type)
219 if (Type == target_type)
222 if (TypeManager.IsEnumType (target_type)) {
223 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
227 return new EnumConstant (c, target_type);
230 return ConvertExplicitly (ec.ConstantCheckState, target_type);
233 public abstract Constant Increment ();
236 /// Need to pass type as the constant can require a boxing
237 /// and in such case no optimization is possible
239 public bool IsDefaultInitializer (Type type)
242 return IsDefaultValue;
244 return Type == TypeManager.null_type;
247 public abstract bool IsDefaultValue {
251 public abstract bool IsNegative {
256 // Returns true iff 1) the stack type of this is one of Object,
257 // int32, int64 and 2) this == 0 or this == null.
259 public virtual bool IsZeroInteger {
260 get { return false; }
264 public abstract class IntegralConstant : Constant {
265 protected IntegralConstant (Location loc) :
270 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
273 ConvertExplicitly (true, target);
274 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
278 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
279 GetValue ().ToString (), TypeManager.CSharpName (target));
284 public class BoolConstant : Constant {
285 public readonly bool Value;
287 public BoolConstant (bool val, Location loc):
290 type = TypeManager.bool_type;
291 eclass = ExprClass.Value;
296 override public string AsString ()
298 return Value ? "true" : "false";
301 public override object GetValue ()
303 return (object) Value;
307 public override void Emit (EmitContext ec)
310 ec.ig.Emit (OpCodes.Ldc_I4_1);
312 ec.ig.Emit (OpCodes.Ldc_I4_0);
315 public override Constant Increment ()
317 throw new NotSupportedException ();
320 public override bool IsDefaultValue {
326 public override bool IsNegative {
332 public override bool IsZeroInteger {
333 get { return Value == false; }
336 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
343 public class ByteConstant : IntegralConstant {
344 public readonly byte Value;
346 public ByteConstant (byte v, Location loc):
349 type = TypeManager.byte_type;
350 eclass = ExprClass.Value;
354 public override void Emit (EmitContext ec)
356 IntLiteral.EmitInt (ec.ig, Value);
359 public override string AsString ()
361 return Value.ToString ();
364 public override object GetValue ()
369 public override Constant Increment ()
371 return new ByteConstant (checked ((byte)(Value + 1)), loc);
374 public override bool IsDefaultValue {
380 public override bool IsNegative {
386 public override bool IsZeroInteger {
387 get { return Value == 0; }
390 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
392 if (target_type == TypeManager.sbyte_type) {
393 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
394 return new SByteConstant ((sbyte) Value, Location);
396 if (target_type == TypeManager.short_type)
397 return new ShortConstant ((short) Value, Location);
398 if (target_type == TypeManager.ushort_type)
399 return new UShortConstant ((ushort) Value, Location);
400 if (target_type == TypeManager.int32_type)
401 return new IntConstant ((int) Value, Location);
402 if (target_type == TypeManager.uint32_type)
403 return new UIntConstant ((uint) Value, Location);
404 if (target_type == TypeManager.int64_type)
405 return new LongConstant ((long) Value, Location);
406 if (target_type == TypeManager.uint64_type)
407 return new ULongConstant ((ulong) Value, Location);
408 if (target_type == TypeManager.float_type)
409 return new FloatConstant ((float) Value, Location);
410 if (target_type == TypeManager.double_type)
411 return new DoubleConstant ((double) Value, Location);
412 if (target_type == TypeManager.char_type)
413 return new CharConstant ((char) Value, Location);
414 if (target_type == TypeManager.decimal_type)
415 return new DecimalConstant ((decimal) Value, Location);
422 public class CharConstant : Constant {
423 public readonly char Value;
425 public CharConstant (char v, Location loc):
428 type = TypeManager.char_type;
429 eclass = ExprClass.Value;
433 public override void Emit (EmitContext ec)
435 IntLiteral.EmitInt (ec.ig, Value);
438 static public string descape (char c)
464 return c.ToString ();
467 public override string AsString ()
469 return "\"" + descape (Value) + "\"";
472 public override object GetValue ()
477 public override Constant Increment ()
479 return new CharConstant (checked ((char)(Value + 1)), loc);
482 public override bool IsDefaultValue {
488 public override bool IsNegative {
494 public override bool IsZeroInteger {
495 get { return Value == '\0'; }
498 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
500 if (target_type == TypeManager.byte_type) {
501 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
502 return new ByteConstant ((byte) Value, Location);
504 if (target_type == TypeManager.sbyte_type) {
505 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
506 return new SByteConstant ((sbyte) Value, Location);
508 if (target_type == TypeManager.short_type) {
509 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
510 return new ShortConstant ((short) Value, Location);
512 if (target_type == TypeManager.int32_type)
513 return new IntConstant ((int) Value, Location);
514 if (target_type == TypeManager.uint32_type)
515 return new UIntConstant ((uint) Value, Location);
516 if (target_type == TypeManager.int64_type)
517 return new LongConstant ((long) Value, Location);
518 if (target_type == TypeManager.uint64_type)
519 return new ULongConstant ((ulong) Value, Location);
520 if (target_type == TypeManager.float_type)
521 return new FloatConstant ((float) Value, Location);
522 if (target_type == TypeManager.double_type)
523 return new DoubleConstant ((double) Value, Location);
524 if (target_type == TypeManager.decimal_type)
525 return new DecimalConstant ((decimal) Value, Location);
532 public class SByteConstant : IntegralConstant {
533 public readonly sbyte Value;
535 public SByteConstant (sbyte v, Location loc):
538 type = TypeManager.sbyte_type;
539 eclass = ExprClass.Value;
543 public override void Emit (EmitContext ec)
545 IntLiteral.EmitInt (ec.ig, Value);
548 public override string AsString ()
550 return Value.ToString ();
553 public override object GetValue ()
558 public override Constant Increment ()
560 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
563 public override bool IsDefaultValue {
569 public override bool IsNegative {
575 public override bool IsZeroInteger {
576 get { return Value == 0; }
579 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
581 if (target_type == TypeManager.byte_type) {
582 CheckUnsigned (inCheckedContext, Value);
583 return new ByteConstant ((byte) Value, Location);
585 if (target_type == TypeManager.short_type)
586 return new ShortConstant ((short) Value, Location);
587 if (target_type == TypeManager.ushort_type) {
588 CheckUnsigned (inCheckedContext, Value);
589 return new UShortConstant ((ushort) Value, Location);
590 } if (target_type == TypeManager.int32_type)
591 return new IntConstant ((int) Value, Location);
592 if (target_type == TypeManager.uint32_type) {
593 CheckUnsigned (inCheckedContext, Value);
594 return new UIntConstant ((uint) Value, Location);
595 } if (target_type == TypeManager.int64_type)
596 return new LongConstant ((long) Value, Location);
597 if (target_type == TypeManager.uint64_type) {
598 CheckUnsigned (inCheckedContext, Value);
599 return new ULongConstant ((ulong) Value, Location);
601 if (target_type == TypeManager.float_type)
602 return new FloatConstant ((float) Value, Location);
603 if (target_type == TypeManager.double_type)
604 return new DoubleConstant ((double) Value, Location);
605 if (target_type == TypeManager.char_type) {
606 CheckUnsigned (inCheckedContext, Value);
607 return new CharConstant ((char) Value, Location);
609 if (target_type == TypeManager.decimal_type)
610 return new DecimalConstant ((decimal) Value, Location);
617 public class ShortConstant : IntegralConstant {
618 public readonly short Value;
620 public ShortConstant (short v, Location loc):
623 type = TypeManager.short_type;
624 eclass = ExprClass.Value;
628 public override void Emit (EmitContext ec)
630 IntLiteral.EmitInt (ec.ig, Value);
633 public override string AsString ()
635 return Value.ToString ();
638 public override object GetValue ()
643 public override Constant Increment ()
645 return new ShortConstant (checked((short)(Value + 1)), loc);
648 public override bool IsDefaultValue {
654 public override bool IsZeroInteger {
655 get { return Value == 0; }
658 public override bool IsNegative {
664 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
666 if (target_type == TypeManager.byte_type) {
667 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
668 return new ByteConstant ((byte) Value, Location);
670 if (target_type == TypeManager.sbyte_type) {
671 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
672 return new SByteConstant ((sbyte) Value, Location);
674 if (target_type == TypeManager.ushort_type) {
675 CheckUnsigned (inCheckedContext, Value);
676 return new UShortConstant ((ushort) Value, Location);
678 if (target_type == TypeManager.int32_type)
679 return new IntConstant ((int) Value, Location);
680 if (target_type == TypeManager.uint32_type) {
681 CheckUnsigned (inCheckedContext, Value);
682 return new UIntConstant ((uint) Value, Location);
684 if (target_type == TypeManager.int64_type)
685 return new LongConstant ((long) Value, Location);
686 if (target_type == TypeManager.uint64_type) {
687 CheckUnsigned (inCheckedContext, Value);
688 return new ULongConstant ((ulong) Value, Location);
690 if (target_type == TypeManager.float_type)
691 return new FloatConstant ((float) Value, Location);
692 if (target_type == TypeManager.double_type)
693 return new DoubleConstant ((double) Value, Location);
694 if (target_type == TypeManager.char_type) {
695 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
696 return new CharConstant ((char) Value, Location);
698 if (target_type == TypeManager.decimal_type)
699 return new DecimalConstant ((decimal) Value, Location);
706 public class UShortConstant : IntegralConstant {
707 public readonly ushort Value;
709 public UShortConstant (ushort v, Location loc):
712 type = TypeManager.ushort_type;
713 eclass = ExprClass.Value;
717 public override void Emit (EmitContext ec)
719 IntLiteral.EmitInt (ec.ig, Value);
722 public override string AsString ()
724 return Value.ToString ();
727 public override object GetValue ()
732 public override Constant Increment ()
734 return new UShortConstant (checked((ushort)(Value + 1)), loc);
737 public override bool IsDefaultValue {
743 public override bool IsNegative {
749 public override bool IsZeroInteger {
750 get { return Value == 0; }
753 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
755 if (target_type == TypeManager.byte_type) {
756 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
757 return new ByteConstant ((byte) Value, Location);
759 if (target_type == TypeManager.sbyte_type) {
760 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
761 return new SByteConstant ((sbyte) Value, Location);
763 if (target_type == TypeManager.short_type) {
764 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
765 return new ShortConstant ((short) Value, Location);
767 if (target_type == TypeManager.int32_type)
768 return new IntConstant ((int) Value, Location);
769 if (target_type == TypeManager.uint32_type)
770 return new UIntConstant ((uint) Value, Location);
771 if (target_type == TypeManager.int64_type)
772 return new LongConstant ((long) Value, Location);
773 if (target_type == TypeManager.uint64_type)
774 return new ULongConstant ((ulong) Value, Location);
775 if (target_type == TypeManager.float_type)
776 return new FloatConstant ((float) Value, Location);
777 if (target_type == TypeManager.double_type)
778 return new DoubleConstant ((double) Value, Location);
779 if (target_type == TypeManager.char_type) {
780 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
781 return new CharConstant ((char) Value, Location);
783 if (target_type == TypeManager.decimal_type)
784 return new DecimalConstant ((decimal) Value, Location);
790 public class IntConstant : IntegralConstant {
791 public readonly int Value;
793 public IntConstant (int v, Location loc):
796 type = TypeManager.int32_type;
797 eclass = ExprClass.Value;
801 static public void EmitInt (ILGenerator ig, int i)
805 ig.Emit (OpCodes.Ldc_I4_M1);
809 ig.Emit (OpCodes.Ldc_I4_0);
813 ig.Emit (OpCodes.Ldc_I4_1);
817 ig.Emit (OpCodes.Ldc_I4_2);
821 ig.Emit (OpCodes.Ldc_I4_3);
825 ig.Emit (OpCodes.Ldc_I4_4);
829 ig.Emit (OpCodes.Ldc_I4_5);
833 ig.Emit (OpCodes.Ldc_I4_6);
837 ig.Emit (OpCodes.Ldc_I4_7);
841 ig.Emit (OpCodes.Ldc_I4_8);
845 if (i >= -128 && i <= 127){
846 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
848 ig.Emit (OpCodes.Ldc_I4, i);
853 public override void Emit (EmitContext ec)
855 EmitInt (ec.ig, Value);
858 public override string AsString ()
860 return Value.ToString ();
863 public override object GetValue ()
868 public override Constant Increment ()
870 return new IntConstant (checked(Value + 1), loc);
873 public override bool IsDefaultValue {
879 public override bool IsNegative {
885 public override bool IsZeroInteger {
886 get { return Value == 0; }
889 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
891 if (target_type == TypeManager.byte_type) {
892 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
893 return new ByteConstant ((byte) Value, Location);
895 if (target_type == TypeManager.sbyte_type) {
896 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
897 return new SByteConstant ((sbyte) Value, Location);
899 if (target_type == TypeManager.short_type) {
900 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
901 return new ShortConstant ((short) Value, Location);
903 if (target_type == TypeManager.ushort_type) {
904 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
905 return new UShortConstant ((ushort) Value, Location);
907 if (target_type == TypeManager.uint32_type) {
908 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
909 return new UIntConstant ((uint) Value, Location);
911 if (target_type == TypeManager.int64_type)
912 return new LongConstant ((long) Value, Location);
913 if (target_type == TypeManager.uint64_type) {
914 CheckUnsigned (inCheckedContext, Value);
915 return new ULongConstant ((ulong) Value, Location);
917 if (target_type == TypeManager.float_type)
918 return new FloatConstant ((float) Value, Location);
919 if (target_type == TypeManager.double_type)
920 return new DoubleConstant ((double) Value, Location);
921 if (target_type == TypeManager.char_type) {
922 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
923 return new CharConstant ((char) Value, Location);
925 if (target_type == TypeManager.decimal_type)
926 return new DecimalConstant ((decimal) Value, Location);
931 public override Constant ConvertImplicitly (Type type)
933 if (this.type == type)
936 Constant c = TryImplicitIntConversion (type);
940 return base.ConvertImplicitly (type);
944 /// Attempts to perform an implicit constant conversion of the IntConstant
945 /// into a different data type using casts (See Implicit Constant
946 /// Expression Conversions)
948 Constant TryImplicitIntConversion (Type target_type)
950 if (target_type == TypeManager.sbyte_type) {
951 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
952 return new SByteConstant ((sbyte) Value, loc);
954 else if (target_type == TypeManager.byte_type) {
955 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
956 return new ByteConstant ((byte) Value, loc);
958 else if (target_type == TypeManager.short_type) {
959 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
960 return new ShortConstant ((short) Value, loc);
962 else if (target_type == TypeManager.ushort_type) {
963 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
964 return new UShortConstant ((ushort) Value, loc);
966 else if (target_type == TypeManager.uint32_type) {
968 return new UIntConstant ((uint) Value, loc);
970 else if (target_type == TypeManager.uint64_type) {
972 // we can optimize this case: a positive int32
973 // always fits on a uint64. But we need an opcode
977 return new ULongConstant ((ulong) Value, loc);
979 else if (target_type == TypeManager.double_type)
980 return new DoubleConstant ((double) Value, loc);
981 else if (target_type == TypeManager.float_type)
982 return new FloatConstant ((float) Value, loc);
988 public class UIntConstant : IntegralConstant {
989 public readonly uint Value;
991 public UIntConstant (uint v, Location loc):
994 type = TypeManager.uint32_type;
995 eclass = ExprClass.Value;
999 public override void Emit (EmitContext ec)
1001 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1004 public override string AsString ()
1006 return Value.ToString ();
1009 public override object GetValue ()
1014 public override Constant Increment ()
1016 return new UIntConstant (checked(Value + 1), loc);
1019 public override bool IsDefaultValue {
1025 public override bool IsNegative {
1031 public override bool IsZeroInteger {
1032 get { return Value == 0; }
1035 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1037 if (target_type == TypeManager.byte_type) {
1038 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1039 return new ByteConstant ((byte) Value, Location);
1041 if (target_type == TypeManager.sbyte_type) {
1042 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1043 return new SByteConstant ((sbyte) Value, Location);
1045 if (target_type == TypeManager.short_type) {
1046 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1047 return new ShortConstant ((short) Value, Location);
1049 if (target_type == TypeManager.ushort_type) {
1050 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1051 return new UShortConstant ((ushort) Value, Location);
1053 if (target_type == TypeManager.int32_type) {
1054 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1055 return new IntConstant ((int) Value, Location);
1057 if (target_type == TypeManager.int64_type)
1058 return new LongConstant ((long) Value, Location);
1059 if (target_type == TypeManager.uint64_type)
1060 return new ULongConstant ((ulong) Value, Location);
1061 if (target_type == TypeManager.float_type)
1062 return new FloatConstant ((float) Value, Location);
1063 if (target_type == TypeManager.double_type)
1064 return new DoubleConstant ((double) Value, Location);
1065 if (target_type == TypeManager.char_type) {
1066 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1067 return new CharConstant ((char) Value, Location);
1069 if (target_type == TypeManager.decimal_type)
1070 return new DecimalConstant ((decimal) Value, Location);
1077 public class LongConstant : IntegralConstant {
1078 public readonly long Value;
1080 public LongConstant (long v, Location loc):
1083 type = TypeManager.int64_type;
1084 eclass = ExprClass.Value;
1088 public override void Emit (EmitContext ec)
1090 EmitLong (ec.ig, Value);
1093 static public void EmitLong (ILGenerator ig, long l)
1095 if (l >= int.MinValue && l <= int.MaxValue) {
1096 IntLiteral.EmitInt (ig, unchecked ((int) l));
1097 ig.Emit (OpCodes.Conv_I8);
1100 ig.Emit (OpCodes.Ldc_I8, l);
1103 public override string AsString ()
1105 return Value.ToString ();
1108 public override object GetValue ()
1113 public override Constant Increment ()
1115 return new LongConstant (checked(Value + 1), loc);
1118 public override bool IsDefaultValue {
1124 public override bool IsNegative {
1130 public override bool IsZeroInteger {
1131 get { return Value == 0; }
1134 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1136 if (target_type == TypeManager.byte_type) {
1137 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1138 return new ByteConstant ((byte) Value, Location);
1140 if (target_type == TypeManager.sbyte_type) {
1141 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1142 return new SByteConstant ((sbyte) Value, Location);
1144 if (target_type == TypeManager.short_type) {
1145 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1146 return new ShortConstant ((short) Value, Location);
1148 if (target_type == TypeManager.ushort_type) {
1149 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1150 return new UShortConstant ((ushort) Value, Location);
1152 if (target_type == TypeManager.int32_type) {
1153 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1154 return new IntConstant ((int) Value, Location);
1156 if (target_type == TypeManager.uint32_type) {
1157 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1158 return new UIntConstant ((uint) Value, Location);
1160 if (target_type == TypeManager.uint64_type) {
1161 CheckUnsigned (inCheckedContext, Value);
1162 return new ULongConstant ((ulong) Value, Location);
1164 if (target_type == TypeManager.float_type)
1165 return new FloatConstant ((float) Value, Location);
1166 if (target_type == TypeManager.double_type)
1167 return new DoubleConstant ((double) Value, Location);
1168 if (target_type == TypeManager.char_type) {
1169 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1170 return new CharConstant ((char) Value, Location);
1172 if (target_type == TypeManager.decimal_type)
1173 return new DecimalConstant ((decimal) Value, Location);
1178 public override Constant ConvertImplicitly (Type type)
1180 if (Value >= 0 && type == TypeManager.uint64_type) {
1181 return new ULongConstant ((ulong) Value, loc);
1184 return base.ConvertImplicitly (type);
1188 public class ULongConstant : IntegralConstant {
1189 public readonly ulong Value;
1191 public ULongConstant (ulong v, Location loc):
1194 type = TypeManager.uint64_type;
1195 eclass = ExprClass.Value;
1199 public override void Emit (EmitContext ec)
1201 ILGenerator ig = ec.ig;
1203 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1206 public override string AsString ()
1208 return Value.ToString ();
1211 public override object GetValue ()
1216 public override Constant Increment ()
1218 return new ULongConstant (checked(Value + 1), loc);
1221 public override bool IsDefaultValue {
1227 public override bool IsNegative {
1233 public override bool IsZeroInteger {
1234 get { return Value == 0; }
1237 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1239 if (target_type == TypeManager.byte_type) {
1240 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1241 return new ByteConstant ((byte) Value, Location);
1243 if (target_type == TypeManager.sbyte_type) {
1244 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1245 return new SByteConstant ((sbyte) Value, Location);
1247 if (target_type == TypeManager.short_type) {
1248 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1249 return new ShortConstant ((short) Value, Location);
1251 if (target_type == TypeManager.ushort_type) {
1252 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1253 return new UShortConstant ((ushort) Value, Location);
1255 if (target_type == TypeManager.int32_type) {
1256 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1257 return new IntConstant ((int) Value, Location);
1259 if (target_type == TypeManager.uint32_type) {
1260 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1261 return new UIntConstant ((uint) Value, Location);
1263 if (target_type == TypeManager.int64_type) {
1264 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1265 return new LongConstant ((long) Value, Location);
1267 if (target_type == TypeManager.float_type)
1268 return new FloatConstant ((float) Value, Location);
1269 if (target_type == TypeManager.double_type)
1270 return new DoubleConstant ((double) Value, Location);
1271 if (target_type == TypeManager.char_type) {
1272 CheckRange (inCheckedContext, Value, Char.MaxValue);
1273 return new CharConstant ((char) Value, Location);
1275 if (target_type == TypeManager.decimal_type)
1276 return new DecimalConstant ((decimal) Value, Location);
1283 public class FloatConstant : Constant {
1286 public FloatConstant (float v, Location loc):
1289 type = TypeManager.float_type;
1290 eclass = ExprClass.Value;
1294 public override void Emit (EmitContext ec)
1296 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1299 public override string AsString ()
1301 return Value.ToString ();
1304 public override object GetValue ()
1309 public override Constant Increment ()
1311 return new FloatConstant (checked(Value + 1), loc);
1314 public override bool IsDefaultValue {
1320 public override bool IsNegative {
1326 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1328 if (target_type == TypeManager.byte_type) {
1329 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1330 return new ByteConstant ((byte) Value, Location);
1332 if (target_type == TypeManager.sbyte_type) {
1333 CheckRange (inCheckedContext, Value, sbyte.MinValue, sbyte.MaxValue);
1334 return new SByteConstant ((sbyte) Value, Location);
1336 if (target_type == TypeManager.short_type) {
1337 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1338 return new ShortConstant ((short) Value, Location);
1340 if (target_type == TypeManager.ushort_type) {
1341 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1342 return new UShortConstant ((ushort) Value, Location);
1344 if (target_type == TypeManager.int32_type) {
1345 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1346 return new IntConstant ((int) Value, Location);
1348 if (target_type == TypeManager.uint32_type) {
1349 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1350 return new UIntConstant ((uint) Value, Location);
1352 if (target_type == TypeManager.int64_type) {
1353 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1354 return new LongConstant ((long) Value, Location);
1356 if (target_type == TypeManager.uint64_type) {
1357 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1358 return new ULongConstant ((ulong) Value, Location);
1360 if (target_type == TypeManager.double_type)
1361 return new DoubleConstant ((double) Value, Location);
1362 if (target_type == TypeManager.char_type) {
1363 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1364 return new CharConstant ((char) Value, Location);
1366 if (target_type == TypeManager.decimal_type)
1367 return new DecimalConstant ((decimal) Value, Location);
1374 public class DoubleConstant : Constant {
1375 public double Value;
1377 public DoubleConstant (double v, Location loc):
1380 type = TypeManager.double_type;
1381 eclass = ExprClass.Value;
1385 public override void Emit (EmitContext ec)
1387 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1390 public override string AsString ()
1392 return Value.ToString ();
1395 public override object GetValue ()
1400 public override Constant Increment ()
1402 return new DoubleConstant (checked(Value + 1), loc);
1405 public override bool IsDefaultValue {
1411 public override bool IsNegative {
1417 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1419 if (target_type == TypeManager.byte_type) {
1420 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1421 return new ByteConstant ((byte) Value, Location);
1423 if (target_type == TypeManager.sbyte_type) {
1424 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1425 return new SByteConstant ((sbyte) Value, Location);
1427 if (target_type == TypeManager.short_type) {
1428 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1429 return new ShortConstant ((short) Value, Location);
1431 if (target_type == TypeManager.ushort_type) {
1432 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1433 return new UShortConstant ((ushort) Value, Location);
1435 if (target_type == TypeManager.int32_type) {
1436 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1437 return new IntConstant ((int) Value, Location);
1439 if (target_type == TypeManager.uint32_type) {
1440 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1441 return new UIntConstant ((uint) Value, Location);
1443 if (target_type == TypeManager.int64_type) {
1444 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1445 return new LongConstant ((long) Value, Location);
1447 if (target_type == TypeManager.uint64_type) {
1448 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1449 return new ULongConstant ((ulong) Value, Location);
1451 if (target_type == TypeManager.float_type)
1452 return new FloatConstant ((float) Value, Location);
1453 if (target_type == TypeManager.char_type) {
1454 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1455 return new CharConstant ((char) Value, Location);
1457 if (target_type == TypeManager.decimal_type)
1458 return new DecimalConstant ((decimal) Value, Location);
1465 public class DecimalConstant : Constant {
1466 public readonly decimal Value;
1468 public DecimalConstant (decimal d, Location loc):
1471 type = TypeManager.decimal_type;
1472 eclass = ExprClass.Value;
1476 override public string AsString ()
1478 return Value.ToString ();
1481 public override object GetValue ()
1483 return (object) Value;
1486 public override void Emit (EmitContext ec)
1488 ILGenerator ig = ec.ig;
1490 int [] words = Decimal.GetBits (Value);
1491 int power = (words [3] >> 16) & 0xff;
1493 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1495 IntConstant.EmitInt (ig, (int)Value);
1496 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1502 // FIXME: we could optimize this, and call a better
1506 IntConstant.EmitInt (ig, words [0]);
1507 IntConstant.EmitInt (ig, words [1]);
1508 IntConstant.EmitInt (ig, words [2]);
1511 IntConstant.EmitInt (ig, words [3] >> 31);
1514 IntConstant.EmitInt (ig, power);
1516 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1519 public override Constant Increment ()
1521 return new DecimalConstant (checked (Value + 1), loc);
1524 public override bool IsDefaultValue {
1530 public override bool IsNegative {
1536 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1538 if (target_type == TypeManager.sbyte_type)
1539 return new SByteConstant ((sbyte)Value, loc);
1540 if (target_type == TypeManager.byte_type)
1541 return new ByteConstant ((byte)Value, loc);
1542 if (target_type == TypeManager.short_type)
1543 return new ShortConstant ((short)Value, loc);
1544 if (target_type == TypeManager.ushort_type)
1545 return new UShortConstant ((ushort)Value, loc);
1546 if (target_type == TypeManager.int32_type)
1547 return new IntConstant ((int)Value, loc);
1548 if (target_type == TypeManager.uint32_type)
1549 return new UIntConstant ((uint)Value, loc);
1550 if (target_type == TypeManager.int64_type)
1551 return new LongConstant ((long)Value, loc);
1552 if (target_type == TypeManager.uint64_type)
1553 return new ULongConstant ((ulong)Value, loc);
1554 if (target_type == TypeManager.char_type)
1555 return new CharConstant ((char)Value, loc);
1556 if (target_type == TypeManager.float_type)
1557 return new FloatConstant ((float)Value, loc);
1558 if (target_type == TypeManager.double_type)
1559 return new DoubleConstant ((double)Value, loc);
1566 public class StringConstant : Constant {
1567 public readonly string Value;
1569 public StringConstant (string s, Location loc):
1572 type = TypeManager.string_type;
1573 eclass = ExprClass.Value;
1577 // FIXME: Escape the string.
1578 override public string AsString ()
1580 return "\"" + Value + "\"";
1583 public override object GetValue ()
1588 public override void Emit (EmitContext ec)
1591 ec.ig.Emit (OpCodes.Ldnull);
1593 ec.ig.Emit (OpCodes.Ldstr, Value);
1596 public override Constant Increment ()
1598 throw new NotSupportedException ();
1601 public override bool IsDefaultValue {
1603 return Value == null;
1607 public override bool IsNegative {
1613 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)