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 (out object value)
44 value = GetTypedValue ();
49 /// This is used to obtain the actual value of the literal
50 /// cast into an object.
52 public abstract object GetValue ();
54 public virtual object GetTypedValue ()
60 /// Constants are always born in a fully resolved state
62 public override Expression DoResolve (EmitContext ec)
68 // The various ToXXXX conversion functions are used by the constant
69 // folding evaluator. A null value is returned if the conversion is
72 // Note: not all the patterns for catching `implicit_conv' are the same.
73 // some implicit conversions can never be performed between two types
74 // even if the conversion would be lossless (for example short to uint),
75 // but some conversions are explicitly permitted by the standard provided
76 // that there will be no loss of information (for example, int to uint).
78 public DoubleConstant ToDouble (Location loc)
80 DoubleConstant c = ConvertToDouble ();
83 Error_ValueCannotBeConverted (loc, TypeManager.double_type, false);
88 public FloatConstant ToFloat (Location loc)
90 FloatConstant c = ConvertToFloat ();
93 Error_ValueCannotBeConverted (loc, TypeManager.float_type, false);
98 public ULongConstant ToULong (Location loc)
100 ULongConstant c = ConvertToULong ();
103 Error_ValueCannotBeConverted (loc, TypeManager.uint64_type, false);
108 public LongConstant ToLong (Location loc)
110 LongConstant c = ConvertToLong ();
113 Error_ValueCannotBeConverted (loc, TypeManager.int64_type, false);
118 public UIntConstant ToUInt (Location loc)
120 UIntConstant c = ConvertToUInt ();
123 Error_ValueCannotBeConverted (loc, TypeManager.uint32_type, false);
128 public IntConstant ToInt (Location loc)
130 IntConstant c = ConvertToInt ();
133 Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
138 public DecimalConstant ToDecimal (Location loc)
140 DecimalConstant c = ConvertToDecimal ();
143 Error_ValueCannotBeConverted (loc, TypeManager.decimal_type, false);
148 public virtual Constant ToType (Type type, Location loc)
153 if (type == TypeManager.object_type)
156 if (!Convert.ImplicitStandardConversionExists (this, type)){
157 Error_ValueCannotBeConverted (loc, type, false);
161 // Special-case: The 0 literal can be converted to an enum value,
162 // and ImplicitStandardConversionExists will return true in that case.
163 if (IsZeroInteger && Type == TypeManager.int32_type && TypeManager.IsEnumType (type)) {
164 return new EnumConstant (this, type);
168 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
170 Error_ValueCannotBeConverted (loc, type, false);
173 // We should always catch the error before this is ever
174 // reached, by calling Convert.ImplicitStandardConversionExists
176 throw new Exception (
177 String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
181 if (type == TypeManager.int32_type)
182 retval = new IntConstant ((int) constant_value, loc);
183 else if (type == TypeManager.uint32_type)
184 retval = new UIntConstant ((uint) constant_value, loc);
185 else if (type == TypeManager.int64_type)
186 retval = new LongConstant ((long) constant_value, loc);
187 else if (type == TypeManager.uint64_type)
188 retval = new ULongConstant ((ulong) constant_value, loc);
189 else if (type == TypeManager.float_type)
190 retval = new FloatConstant ((float) constant_value, loc);
191 else if (type == TypeManager.double_type)
192 retval = new DoubleConstant ((double) constant_value, loc);
193 else if (type == TypeManager.string_type)
194 retval = new StringConstant ((string) constant_value, loc);
195 else if (type == TypeManager.short_type)
196 retval = new ShortConstant ((short) constant_value, loc);
197 else if (type == TypeManager.ushort_type)
198 retval = new UShortConstant ((ushort) constant_value, loc);
199 else if (type == TypeManager.sbyte_type)
200 retval = new SByteConstant ((sbyte) constant_value, loc);
201 else if (type == TypeManager.byte_type)
202 retval = new ByteConstant ((byte) constant_value, loc);
203 else if (type == TypeManager.char_type)
204 retval = new CharConstant ((char) constant_value, loc);
205 else if (type == TypeManager.bool_type)
206 retval = new BoolConstant ((bool) constant_value, loc);
207 else if (type == TypeManager.decimal_type)
208 retval = new DecimalConstant ((decimal) constant_value, loc);
210 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
215 protected static void CheckRange (EmitContext ec, ulong value, ulong max)
217 if (!ec.ConstantCheckState)
221 throw new OverflowException ();
224 protected static void CheckRange (EmitContext ec, double value, long min, long max)
226 if (!ec.ConstantCheckState)
229 if (((value < min) || (value > max)))
230 throw new OverflowException ();
233 protected static void CheckUnsigned (EmitContext ec, long value)
235 if (!ec.ConstantCheckState)
239 throw new OverflowException ();
243 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
244 /// It throws OverflowException
246 public abstract Constant Reduce (EmitContext ec, Type target_type);
249 /// Attempts to do a compile-time folding of a constant cast.
251 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
254 return TryReduce (ec, target_type);
256 catch (OverflowException) {
257 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
258 GetValue ().ToString (), TypeManager.CSharpName (target_type));
263 Constant TryReduce (EmitContext ec, Type target_type)
265 if (Type == target_type)
268 if (TypeManager.IsEnumType (target_type)) {
269 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
273 return new EnumConstant (c, target_type);
276 return Reduce (ec, target_type);
280 public virtual DecimalConstant ConvertToDecimal ()
285 public virtual DoubleConstant ConvertToDouble ()
290 public virtual FloatConstant ConvertToFloat ()
295 public virtual ULongConstant ConvertToULong ()
300 public virtual LongConstant ConvertToLong ()
305 public virtual UIntConstant ConvertToUInt ()
310 public virtual IntConstant ConvertToInt ()
315 public abstract Constant Increment ();
317 public abstract bool IsDefaultValue {
321 public abstract bool IsNegative {
326 // Returns true iff 1) the stack type of this is one of Object,
327 // int32, int64 and 2) this == 0 or this == null.
329 public virtual bool IsZeroInteger {
330 get { return false; }
334 public class BoolConstant : Constant {
335 public readonly bool Value;
337 public BoolConstant (bool val, Location loc):
340 type = TypeManager.bool_type;
341 eclass = ExprClass.Value;
346 override public string AsString ()
348 return Value ? "true" : "false";
351 public override object GetValue ()
353 return (object) Value;
357 public override void Emit (EmitContext ec)
360 ec.ig.Emit (OpCodes.Ldc_I4_1);
362 ec.ig.Emit (OpCodes.Ldc_I4_0);
365 public override Constant Increment ()
367 throw new NotSupportedException ();
370 public override bool IsDefaultValue {
376 public override bool IsNegative {
382 public override bool IsZeroInteger {
383 get { return Value == false; }
386 public override Constant Reduce (EmitContext ec, Type target_type)
393 public class ByteConstant : Constant {
394 public readonly byte Value;
396 public ByteConstant (byte v, Location loc):
399 type = TypeManager.byte_type;
400 eclass = ExprClass.Value;
404 public override void Emit (EmitContext ec)
406 IntLiteral.EmitInt (ec.ig, Value);
409 public override string AsString ()
411 return Value.ToString ();
414 public override object GetValue ()
419 public override DoubleConstant ConvertToDouble ()
421 return new DoubleConstant (Value, loc);
424 public override FloatConstant ConvertToFloat ()
426 return new FloatConstant (Value, loc);
429 public override ULongConstant ConvertToULong ()
431 return new ULongConstant (Value, loc);
434 public override LongConstant ConvertToLong ()
436 return new LongConstant (Value, loc);
439 public override UIntConstant ConvertToUInt ()
441 return new UIntConstant (Value, loc);
444 public override IntConstant ConvertToInt ()
446 return new IntConstant (Value, loc);
449 public override Constant Increment ()
451 return new ByteConstant (checked ((byte)(Value + 1)), loc);
454 public override bool IsDefaultValue {
460 public override bool IsNegative {
466 public override bool IsZeroInteger {
467 get { return Value == 0; }
470 public override Constant Reduce (EmitContext ec, Type target_type)
472 if (target_type == TypeManager.sbyte_type) {
473 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
474 return new SByteConstant ((sbyte) Value, Location);
476 if (target_type == TypeManager.short_type)
477 return new ShortConstant ((short) Value, Location);
478 if (target_type == TypeManager.ushort_type)
479 return new UShortConstant ((ushort) Value, Location);
480 if (target_type == TypeManager.int32_type)
481 return new IntConstant ((int) Value, Location);
482 if (target_type == TypeManager.uint32_type)
483 return new UIntConstant ((uint) Value, Location);
484 if (target_type == TypeManager.int64_type)
485 return new LongConstant ((long) Value, Location);
486 if (target_type == TypeManager.uint64_type)
487 return new ULongConstant ((ulong) Value, Location);
488 if (target_type == TypeManager.float_type)
489 return new FloatConstant ((float) Value, Location);
490 if (target_type == TypeManager.double_type)
491 return new DoubleConstant ((double) Value, Location);
492 if (target_type == TypeManager.char_type)
493 return new CharConstant ((char) Value, Location);
494 if (target_type == TypeManager.decimal_type)
495 return new DecimalConstant ((decimal) Value, Location);
502 public class CharConstant : Constant {
503 public readonly char Value;
505 public CharConstant (char v, Location loc):
508 type = TypeManager.char_type;
509 eclass = ExprClass.Value;
513 public override void Emit (EmitContext ec)
515 IntLiteral.EmitInt (ec.ig, Value);
518 static public string descape (char c)
544 return c.ToString ();
547 public override string AsString ()
549 return "\"" + descape (Value) + "\"";
552 public override object GetValue ()
557 public override DoubleConstant ConvertToDouble ()
559 return new DoubleConstant (Value, loc);
562 public override FloatConstant ConvertToFloat ()
564 return new FloatConstant (Value, loc);
567 public override ULongConstant ConvertToULong ()
569 return new ULongConstant (Value, loc);
572 public override LongConstant ConvertToLong ()
574 return new LongConstant (Value, loc);
577 public override UIntConstant ConvertToUInt ()
579 return new UIntConstant (Value, loc);
582 public override IntConstant ConvertToInt ()
584 return new IntConstant (Value, loc);
587 public override Constant Increment ()
589 return new CharConstant (checked ((char)(Value + 1)), loc);
592 public override bool IsDefaultValue {
598 public override bool IsNegative {
604 public override bool IsZeroInteger {
605 get { return Value == '\0'; }
608 public override Constant Reduce (EmitContext ec, Type target_type)
610 if (target_type == TypeManager.byte_type) {
611 CheckRange (ec, Value, Byte.MinValue, Byte.MaxValue);
612 return new ByteConstant ((byte) Value, Location);
614 if (target_type == TypeManager.sbyte_type) {
615 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
616 return new SByteConstant ((sbyte) Value, Location);
618 if (target_type == TypeManager.short_type) {
619 CheckRange (ec, Value, Int16.MinValue, Int16.MaxValue);
620 return new ShortConstant ((short) Value, Location);
622 if (target_type == TypeManager.int32_type)
623 return new IntConstant ((int) Value, Location);
624 if (target_type == TypeManager.uint32_type)
625 return new UIntConstant ((uint) Value, Location);
626 if (target_type == TypeManager.int64_type)
627 return new LongConstant ((long) Value, Location);
628 if (target_type == TypeManager.uint64_type)
629 return new ULongConstant ((ulong) Value, Location);
630 if (target_type == TypeManager.float_type)
631 return new FloatConstant ((float) Value, Location);
632 if (target_type == TypeManager.double_type)
633 return new DoubleConstant ((double) Value, Location);
634 if (target_type == TypeManager.decimal_type)
635 return new DecimalConstant ((decimal) Value, Location);
642 public class SByteConstant : Constant {
643 public readonly sbyte Value;
645 public SByteConstant (sbyte v, Location loc):
648 type = TypeManager.sbyte_type;
649 eclass = ExprClass.Value;
653 public override void Emit (EmitContext ec)
655 IntLiteral.EmitInt (ec.ig, Value);
658 public override string AsString ()
660 return Value.ToString ();
663 public override object GetValue ()
668 public override DoubleConstant ConvertToDouble ()
670 return new DoubleConstant (Value, loc);
673 public override FloatConstant ConvertToFloat ()
675 return new FloatConstant (Value, loc);
678 public override ULongConstant ConvertToULong ()
681 return new ULongConstant ((ulong) Value, loc);
686 public override LongConstant ConvertToLong ()
688 return new LongConstant (Value, loc);
691 public override UIntConstant ConvertToUInt ()
696 public override IntConstant ConvertToInt ()
698 return new IntConstant (Value, loc);
701 public override Constant Increment ()
703 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
706 public override bool IsDefaultValue {
712 public override bool IsNegative {
718 public override bool IsZeroInteger {
719 get { return Value == 0; }
722 public override Constant Reduce (EmitContext ec, Type target_type)
724 if (target_type == TypeManager.byte_type) {
725 CheckUnsigned (ec, Value);
726 return new ByteConstant ((byte) Value, Location);
728 if (target_type == TypeManager.short_type)
729 return new ShortConstant ((short) Value, Location);
730 if (target_type == TypeManager.ushort_type) {
731 CheckUnsigned (ec, Value);
732 return new UShortConstant ((ushort) Value, Location);
733 } if (target_type == TypeManager.int32_type)
734 return new IntConstant ((int) Value, Location);
735 if (target_type == TypeManager.uint32_type) {
736 CheckUnsigned (ec, Value);
737 return new UIntConstant ((uint) Value, Location);
738 } if (target_type == TypeManager.int64_type)
739 return new LongConstant ((long) Value, Location);
740 if (target_type == TypeManager.uint64_type) {
741 CheckUnsigned (ec, Value);
742 return new ULongConstant ((ulong) Value, Location);
744 if (target_type == TypeManager.float_type)
745 return new FloatConstant ((float) Value, Location);
746 if (target_type == TypeManager.double_type)
747 return new DoubleConstant ((double) Value, Location);
748 if (target_type == TypeManager.char_type) {
749 CheckUnsigned (ec, Value);
750 return new CharConstant ((char) Value, Location);
752 if (target_type == TypeManager.decimal_type)
753 return new DecimalConstant ((decimal) Value, Location);
760 public class ShortConstant : Constant {
761 public readonly short Value;
763 public ShortConstant (short v, Location loc):
766 type = TypeManager.short_type;
767 eclass = ExprClass.Value;
771 public override void Emit (EmitContext ec)
773 IntLiteral.EmitInt (ec.ig, Value);
776 public override string AsString ()
778 return Value.ToString ();
781 public override object GetValue ()
786 public override DoubleConstant ConvertToDouble ()
788 return new DoubleConstant (Value, loc);
791 public override FloatConstant ConvertToFloat ()
793 return new FloatConstant (Value, loc);
796 public override ULongConstant ConvertToULong ()
801 public override LongConstant ConvertToLong ()
803 return new LongConstant (Value, loc);
806 public override UIntConstant ConvertToUInt ()
811 public override IntConstant ConvertToInt ()
813 return new IntConstant (Value, loc);
816 public override Constant Increment ()
818 return new ShortConstant (checked((short)(Value + 1)), loc);
821 public override bool IsDefaultValue {
827 public override bool IsZeroInteger {
828 get { return Value == 0; }
831 public override bool IsNegative {
837 public override Constant Reduce (EmitContext ec, Type target_type)
839 if (target_type == TypeManager.byte_type) {
840 CheckRange (ec, Value, Byte.MinValue, Byte.MaxValue);
841 return new ByteConstant ((byte) Value, Location);
843 if (target_type == TypeManager.sbyte_type) {
844 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
845 return new SByteConstant ((sbyte) Value, Location);
847 if (target_type == TypeManager.ushort_type) {
848 CheckUnsigned (ec, Value);
849 return new UShortConstant ((ushort) Value, Location);
851 if (target_type == TypeManager.int32_type)
852 return new IntConstant ((int) Value, Location);
853 if (target_type == TypeManager.uint32_type) {
854 CheckUnsigned (ec, Value);
855 return new UIntConstant ((uint) Value, Location);
857 if (target_type == TypeManager.int64_type)
858 return new LongConstant ((long) Value, Location);
859 if (target_type == TypeManager.uint64_type) {
860 CheckUnsigned (ec, Value);
861 return new ULongConstant ((ulong) Value, Location);
863 if (target_type == TypeManager.float_type)
864 return new FloatConstant ((float) Value, Location);
865 if (target_type == TypeManager.double_type)
866 return new DoubleConstant ((double) Value, Location);
867 if (target_type == TypeManager.char_type) {
868 CheckRange (ec, Value, Char.MinValue, Char.MaxValue);
869 return new CharConstant ((char) Value, Location);
871 if (target_type == TypeManager.decimal_type)
872 return new DecimalConstant ((decimal) Value, Location);
879 public class UShortConstant : Constant {
880 public readonly ushort Value;
882 public UShortConstant (ushort v, Location loc):
885 type = TypeManager.ushort_type;
886 eclass = ExprClass.Value;
890 public override void Emit (EmitContext ec)
892 IntLiteral.EmitInt (ec.ig, Value);
895 public override string AsString ()
897 return Value.ToString ();
900 public override object GetValue ()
905 public override DoubleConstant ConvertToDouble ()
907 return new DoubleConstant (Value, loc);
910 public override FloatConstant ConvertToFloat ()
912 return new FloatConstant (Value, loc);
915 public override ULongConstant ConvertToULong ()
917 return new ULongConstant (Value, loc);
920 public override LongConstant ConvertToLong ()
922 return new LongConstant (Value, loc);
925 public override UIntConstant ConvertToUInt ()
927 return new UIntConstant (Value, loc);
930 public override IntConstant ConvertToInt ()
932 return new IntConstant (Value, loc);
935 public override Constant Increment ()
937 return new UShortConstant (checked((ushort)(Value + 1)), loc);
940 public override bool IsDefaultValue {
946 public override bool IsNegative {
952 public override bool IsZeroInteger {
953 get { return Value == 0; }
956 public override Constant Reduce (EmitContext ec, Type target_type)
958 if (target_type == TypeManager.byte_type) {
959 CheckRange (ec, Value, Byte.MinValue, Byte.MaxValue);
960 return new ByteConstant ((byte) Value, Location);
962 if (target_type == TypeManager.sbyte_type) {
963 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
964 return new SByteConstant ((sbyte) Value, Location);
966 if (target_type == TypeManager.short_type) {
967 CheckRange (ec, Value, Int16.MinValue, Int16.MaxValue);
968 return new ShortConstant ((short) Value, Location);
970 if (target_type == TypeManager.int32_type)
971 return new IntConstant ((int) Value, Location);
972 if (target_type == TypeManager.uint32_type)
973 return new UIntConstant ((uint) Value, Location);
974 if (target_type == TypeManager.int64_type)
975 return new LongConstant ((long) Value, Location);
976 if (target_type == TypeManager.uint64_type)
977 return new ULongConstant ((ulong) Value, Location);
978 if (target_type == TypeManager.float_type)
979 return new FloatConstant ((float) Value, Location);
980 if (target_type == TypeManager.double_type)
981 return new DoubleConstant ((double) Value, Location);
982 if (target_type == TypeManager.char_type) {
983 CheckRange (ec, Value, Char.MinValue, Char.MaxValue);
984 return new CharConstant ((char) Value, Location);
986 if (target_type == TypeManager.decimal_type)
987 return new DecimalConstant ((decimal) Value, Location);
993 public class IntConstant : Constant {
994 public readonly int Value;
996 public IntConstant (int v, Location loc):
999 type = TypeManager.int32_type;
1000 eclass = ExprClass.Value;
1004 static public void EmitInt (ILGenerator ig, int i)
1008 ig.Emit (OpCodes.Ldc_I4_M1);
1012 ig.Emit (OpCodes.Ldc_I4_0);
1016 ig.Emit (OpCodes.Ldc_I4_1);
1020 ig.Emit (OpCodes.Ldc_I4_2);
1024 ig.Emit (OpCodes.Ldc_I4_3);
1028 ig.Emit (OpCodes.Ldc_I4_4);
1032 ig.Emit (OpCodes.Ldc_I4_5);
1036 ig.Emit (OpCodes.Ldc_I4_6);
1040 ig.Emit (OpCodes.Ldc_I4_7);
1044 ig.Emit (OpCodes.Ldc_I4_8);
1048 if (i >= -128 && i <= 127){
1049 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
1051 ig.Emit (OpCodes.Ldc_I4, i);
1056 public override void Emit (EmitContext ec)
1058 EmitInt (ec.ig, Value);
1061 public override string AsString ()
1063 return Value.ToString ();
1066 public override object GetValue ()
1071 public override DecimalConstant ConvertToDecimal()
1073 return new DecimalConstant (Value, loc);
1076 public override DoubleConstant ConvertToDouble ()
1078 return new DoubleConstant (Value, loc);
1081 public override FloatConstant ConvertToFloat ()
1083 return new FloatConstant (Value, loc);
1086 public override ULongConstant ConvertToULong ()
1091 return new ULongConstant ((ulong) Value, loc);
1094 public override LongConstant ConvertToLong ()
1096 return new LongConstant (Value, loc);
1099 public override UIntConstant ConvertToUInt ()
1104 return new UIntConstant ((uint) Value, loc);
1107 public override IntConstant ConvertToInt ()
1112 public override Constant Increment ()
1114 return new IntConstant (checked(Value + 1), loc);
1117 public override bool IsDefaultValue {
1123 public override bool IsNegative {
1129 public override bool IsZeroInteger {
1130 get { return Value == 0; }
1133 public override Constant Reduce (EmitContext ec, Type target_type)
1135 if (target_type == TypeManager.byte_type) {
1136 CheckRange (ec, Value, Byte.MinValue, Byte.MaxValue);
1137 return new ByteConstant ((byte) Value, Location);
1139 if (target_type == TypeManager.sbyte_type) {
1140 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
1141 return new SByteConstant ((sbyte) Value, Location);
1143 if (target_type == TypeManager.short_type) {
1144 CheckRange (ec, Value, Int16.MinValue, Int16.MaxValue);
1145 return new ShortConstant ((short) Value, Location);
1147 if (target_type == TypeManager.ushort_type) {
1148 CheckRange (ec, Value, UInt16.MinValue, UInt16.MaxValue);
1149 return new UShortConstant ((ushort) Value, Location);
1151 if (target_type == TypeManager.uint32_type) {
1152 CheckRange (ec, Value, Int32.MinValue, Int32.MaxValue);
1153 return new UIntConstant ((uint) Value, Location);
1155 if (target_type == TypeManager.int64_type)
1156 return new LongConstant ((long) Value, Location);
1157 if (target_type == TypeManager.uint64_type) {
1158 CheckUnsigned (ec, Value);
1159 return new ULongConstant ((ulong) Value, Location);
1161 if (target_type == TypeManager.float_type)
1162 return new FloatConstant ((float) Value, Location);
1163 if (target_type == TypeManager.double_type)
1164 return new DoubleConstant ((double) Value, Location);
1165 if (target_type == TypeManager.char_type) {
1166 CheckRange (ec, Value, Char.MinValue, Char.MaxValue);
1167 return new CharConstant ((char) Value, Location);
1169 if (target_type == TypeManager.decimal_type)
1170 return new DecimalConstant ((decimal) Value, Location);
1176 public class UIntConstant : Constant {
1177 public readonly uint Value;
1179 public UIntConstant (uint v, Location loc):
1182 type = TypeManager.uint32_type;
1183 eclass = ExprClass.Value;
1187 public override void Emit (EmitContext ec)
1189 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1192 public override string AsString ()
1194 return Value.ToString ();
1197 public override object GetValue ()
1202 public override DoubleConstant ConvertToDouble ()
1204 return new DoubleConstant (Value, loc);
1207 public override FloatConstant ConvertToFloat ()
1209 return new FloatConstant (Value, loc);
1212 public override ULongConstant ConvertToULong ()
1214 return new ULongConstant (Value, loc);
1217 public override LongConstant ConvertToLong ()
1219 return new LongConstant (Value, loc);
1222 public override UIntConstant ConvertToUInt ()
1227 public override IntConstant ConvertToInt ()
1232 public override Constant Increment ()
1234 return new UIntConstant (checked(Value + 1), loc);
1237 public override bool IsDefaultValue {
1243 public override bool IsNegative {
1249 public override bool IsZeroInteger {
1250 get { return Value == 0; }
1253 public override Constant Reduce (EmitContext ec, Type target_type)
1255 if (target_type == TypeManager.byte_type) {
1256 CheckRange (ec, Value, Char.MinValue, Char.MaxValue);
1257 return new ByteConstant ((byte) Value, Location);
1259 if (target_type == TypeManager.sbyte_type) {
1260 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
1261 return new SByteConstant ((sbyte) Value, Location);
1263 if (target_type == TypeManager.short_type) {
1264 CheckRange (ec, Value, Int16.MinValue, Int16.MaxValue);
1265 return new ShortConstant ((short) Value, Location);
1267 if (target_type == TypeManager.ushort_type) {
1268 CheckRange (ec, Value, UInt16.MinValue, UInt16.MaxValue);
1269 return new UShortConstant ((ushort) Value, Location);
1271 if (target_type == TypeManager.int32_type) {
1272 CheckRange (ec, Value, Int32.MinValue, Int32.MaxValue);
1273 return new IntConstant ((int) Value, Location);
1275 if (target_type == TypeManager.int64_type)
1276 return new LongConstant ((long) Value, Location);
1277 if (target_type == TypeManager.uint64_type)
1278 return new ULongConstant ((ulong) Value, Location);
1279 if (target_type == TypeManager.float_type)
1280 return new FloatConstant ((float) Value, Location);
1281 if (target_type == TypeManager.double_type)
1282 return new DoubleConstant ((double) Value, Location);
1283 if (target_type == TypeManager.char_type) {
1284 CheckRange (ec, Value, Char.MinValue, Char.MaxValue);
1285 return new CharConstant ((char) Value, Location);
1287 if (target_type == TypeManager.decimal_type)
1288 return new DecimalConstant ((decimal) Value, Location);
1295 public class LongConstant : Constant {
1296 public readonly long Value;
1298 public LongConstant (long v, Location loc):
1301 type = TypeManager.int64_type;
1302 eclass = ExprClass.Value;
1306 public override void Emit (EmitContext ec)
1308 ILGenerator ig = ec.ig;
1310 EmitLong (ig, Value);
1313 static public void EmitLong (ILGenerator ig, long l)
1315 if ((l >> 32) == 0){
1316 IntLiteral.EmitInt (ig, unchecked ((int) l));
1317 ig.Emit (OpCodes.Conv_U8);
1319 ig.Emit (OpCodes.Ldc_I8, l);
1323 public override string AsString ()
1325 return Value.ToString ();
1328 public override object GetValue ()
1333 public override DoubleConstant ConvertToDouble ()
1335 return new DoubleConstant (Value, loc);
1338 public override FloatConstant ConvertToFloat ()
1340 return new FloatConstant (Value, loc);
1343 public override ULongConstant ConvertToULong ()
1348 return new ULongConstant ((ulong) Value, loc);
1351 public override LongConstant ConvertToLong ()
1356 public override UIntConstant ConvertToUInt ()
1361 public override IntConstant ConvertToInt ()
1366 public override Constant Increment ()
1368 return new LongConstant (checked(Value + 1), loc);
1371 public override bool IsDefaultValue {
1377 public override bool IsNegative {
1383 public override bool IsZeroInteger {
1384 get { return Value == 0; }
1387 public override Constant Reduce (EmitContext ec, Type target_type)
1389 if (target_type == TypeManager.byte_type) {
1390 CheckRange (ec, Value, Byte.MinValue, Byte.MaxValue);
1391 return new ByteConstant ((byte) Value, Location);
1393 if (target_type == TypeManager.sbyte_type) {
1394 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
1395 return new SByteConstant ((sbyte) Value, Location);
1397 if (target_type == TypeManager.short_type) {
1398 CheckRange (ec, Value, Int16.MinValue, Int16.MaxValue);
1399 return new ShortConstant ((short) Value, Location);
1401 if (target_type == TypeManager.ushort_type) {
1402 CheckRange (ec, Value, UInt16.MinValue, UInt16.MaxValue);
1403 return new UShortConstant ((ushort) Value, Location);
1405 if (target_type == TypeManager.int32_type) {
1406 CheckRange (ec, Value, Int32.MinValue, Int32.MaxValue);
1407 return new IntConstant ((int) Value, Location);
1409 if (target_type == TypeManager.uint32_type) {
1410 CheckRange (ec, Value, UInt32.MinValue, UInt32.MaxValue);
1411 return new UIntConstant ((uint) Value, Location);
1413 if (target_type == TypeManager.uint64_type) {
1414 CheckUnsigned (ec, Value);
1415 return new ULongConstant ((ulong) Value, Location);
1417 if (target_type == TypeManager.float_type)
1418 return new FloatConstant ((float) Value, Location);
1419 if (target_type == TypeManager.double_type)
1420 return new DoubleConstant ((double) Value, Location);
1421 if (target_type == TypeManager.char_type) {
1422 CheckRange (ec, Value, Char.MinValue, Char.MaxValue);
1423 return new CharConstant ((char) Value, Location);
1425 if (target_type == TypeManager.decimal_type)
1426 return new DecimalConstant ((decimal) Value, Location);
1433 public class ULongConstant : Constant {
1434 public readonly ulong Value;
1436 public ULongConstant (ulong v, Location loc):
1439 type = TypeManager.uint64_type;
1440 eclass = ExprClass.Value;
1444 public override void Emit (EmitContext ec)
1446 ILGenerator ig = ec.ig;
1448 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1451 public override string AsString ()
1453 return Value.ToString ();
1456 public override object GetValue ()
1461 public override DoubleConstant ConvertToDouble ()
1463 return new DoubleConstant (Value, loc);
1466 public override FloatConstant ConvertToFloat ()
1468 return new FloatConstant (Value, loc);
1471 public override ULongConstant ConvertToULong ()
1476 public override LongConstant ConvertToLong ()
1481 public override UIntConstant ConvertToUInt ()
1486 public override IntConstant ConvertToInt ()
1491 public override Constant Increment ()
1493 return new ULongConstant (checked(Value + 1), loc);
1496 public override bool IsDefaultValue {
1502 public override bool IsNegative {
1508 public override bool IsZeroInteger {
1509 get { return Value == 0; }
1512 public override Constant Reduce (EmitContext ec, Type target_type)
1514 if (target_type == TypeManager.byte_type) {
1515 CheckRange (ec, Value, Byte.MaxValue);
1516 return new ByteConstant ((byte) Value, Location);
1518 if (target_type == TypeManager.sbyte_type) {
1519 CheckRange (ec, Value, (ulong) SByte.MaxValue);
1520 return new SByteConstant ((sbyte) Value, Location);
1522 if (target_type == TypeManager.short_type) {
1523 CheckRange (ec, Value, (ulong) Int16.MaxValue);
1524 return new ShortConstant ((short) Value, Location);
1526 if (target_type == TypeManager.ushort_type) {
1527 CheckRange (ec, Value, UInt16.MaxValue);
1528 return new UShortConstant ((ushort) Value, Location);
1530 if (target_type == TypeManager.int32_type) {
1531 CheckRange (ec, Value, Int32.MaxValue);
1532 return new IntConstant ((int) Value, Location);
1534 if (target_type == TypeManager.uint32_type) {
1535 CheckRange (ec, Value, UInt32.MaxValue);
1536 return new UIntConstant ((uint) Value, Location);
1538 if (target_type == TypeManager.int64_type) {
1539 CheckRange (ec, Value, (ulong) Int64.MaxValue);
1540 return new LongConstant ((long) Value, Location);
1542 if (target_type == TypeManager.float_type)
1543 return new FloatConstant ((float) Value, Location);
1544 if (target_type == TypeManager.double_type)
1545 return new DoubleConstant ((double) Value, Location);
1546 if (target_type == TypeManager.char_type) {
1547 CheckRange (ec, Value, Char.MaxValue);
1548 return new CharConstant ((char) Value, Location);
1550 if (target_type == TypeManager.decimal_type)
1551 return new DecimalConstant ((decimal) Value, Location);
1558 public class FloatConstant : Constant {
1559 public readonly float Value;
1561 public FloatConstant (float v, Location loc):
1564 type = TypeManager.float_type;
1565 eclass = ExprClass.Value;
1569 public override void Emit (EmitContext ec)
1571 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1574 public override string AsString ()
1576 return Value.ToString ();
1579 public override object GetValue ()
1584 public override DoubleConstant ConvertToDouble ()
1586 return new DoubleConstant (Value, loc);
1589 public override FloatConstant ConvertToFloat ()
1594 public override LongConstant ConvertToLong ()
1599 public override UIntConstant ConvertToUInt ()
1604 public override IntConstant ConvertToInt ()
1609 public override Constant Increment ()
1611 return new FloatConstant (checked(Value + 1), loc);
1614 public override bool IsDefaultValue {
1620 public override bool IsNegative {
1626 public override Constant Reduce (EmitContext ec, Type target_type)
1628 if (target_type == TypeManager.byte_type)
1629 return new ByteConstant ((byte) Value, Location);
1630 if (target_type == TypeManager.sbyte_type)
1631 return new SByteConstant ((sbyte) Value, Location);
1632 if (target_type == TypeManager.short_type)
1633 return new ShortConstant ((short) Value, Location);
1634 if (target_type == TypeManager.ushort_type)
1635 return new UShortConstant ((ushort) Value, Location);
1636 if (target_type == TypeManager.int32_type)
1637 return new IntConstant ((int) Value, Location);
1638 if (target_type == TypeManager.uint32_type)
1639 return new UIntConstant ((uint) Value, Location);
1640 if (target_type == TypeManager.int64_type)
1641 return new LongConstant ((long) Value, Location);
1642 if (target_type == TypeManager.uint64_type)
1643 return new ULongConstant ((ulong) Value, Location);
1644 if (target_type == TypeManager.double_type)
1645 return new DoubleConstant ((double) Value, Location);
1646 if (target_type == TypeManager.char_type)
1647 return new CharConstant ((char) Value, Location);
1648 if (target_type == TypeManager.decimal_type)
1649 return new DecimalConstant ((decimal) Value, Location);
1656 public class DoubleConstant : Constant {
1657 public readonly double Value;
1659 public DoubleConstant (double v, Location loc):
1662 type = TypeManager.double_type;
1663 eclass = ExprClass.Value;
1667 public override void Emit (EmitContext ec)
1669 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1672 public override string AsString ()
1674 return Value.ToString ();
1677 public override object GetValue ()
1682 public override DoubleConstant ConvertToDouble ()
1687 public override FloatConstant ConvertToFloat ()
1692 public override ULongConstant ConvertToULong ()
1697 public override LongConstant ConvertToLong ()
1702 public override UIntConstant ConvertToUInt ()
1707 public override IntConstant ConvertToInt ()
1712 public override Constant Increment ()
1714 return new DoubleConstant (checked(Value + 1), loc);
1717 public override bool IsDefaultValue {
1723 public override bool IsNegative {
1729 public override Constant Reduce (EmitContext ec, Type target_type)
1731 if (target_type == TypeManager.byte_type) {
1732 CheckRange (ec, Value, Byte.MinValue, Byte.MaxValue);
1733 return new ByteConstant ((byte) Value, Location);
1735 if (target_type == TypeManager.sbyte_type) {
1736 CheckRange (ec, Value, SByte.MinValue, SByte.MaxValue);
1737 return new SByteConstant ((sbyte) Value, Location);
1739 if (target_type == TypeManager.short_type)
1740 return new ShortConstant ((short) Value, Location);
1741 if (target_type == TypeManager.ushort_type)
1742 return new UShortConstant ((ushort) Value, Location);
1743 if (target_type == TypeManager.int32_type)
1744 return new IntConstant ((int) Value, Location);
1745 if (target_type == TypeManager.uint32_type)
1746 return new UIntConstant ((uint) Value, Location);
1747 if (target_type == TypeManager.int64_type)
1748 return new LongConstant ((long) Value, Location);
1749 if (target_type == TypeManager.uint64_type)
1750 return new ULongConstant ((ulong) Value, Location);
1751 if (target_type == TypeManager.float_type)
1752 return new FloatConstant ((float) Value, Location);
1753 if (target_type == TypeManager.char_type) {
1754 CheckRange (ec, Value, char.MinValue, char.MaxValue);
1755 return new CharConstant ((char) Value, Location);
1757 if (target_type == TypeManager.decimal_type)
1758 return new DecimalConstant ((decimal) Value, Location);
1765 public class DecimalConstant : Constant {
1766 public readonly decimal Value;
1768 public DecimalConstant (decimal d, Location loc):
1771 type = TypeManager.decimal_type;
1772 eclass = ExprClass.Value;
1776 override public string AsString ()
1778 return Value.ToString ();
1781 public override object GetValue ()
1783 return (object) Value;
1786 public override void Emit (EmitContext ec)
1788 ILGenerator ig = ec.ig;
1790 int [] words = Decimal.GetBits (Value);
1791 int power = (words [3] >> 16) & 0xff;
1793 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1795 IntConstant.EmitInt (ig, (int)Value);
1796 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1802 // FIXME: we could optimize this, and call a better
1806 IntConstant.EmitInt (ig, words [0]);
1807 IntConstant.EmitInt (ig, words [1]);
1808 IntConstant.EmitInt (ig, words [2]);
1811 IntConstant.EmitInt (ig, words [3] >> 31);
1814 IntConstant.EmitInt (ig, power);
1816 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1819 public override Constant Increment ()
1821 return new DecimalConstant (checked (Value + 1), loc);
1824 public override bool IsDefaultValue {
1830 public override bool IsNegative {
1836 public override Constant Reduce (EmitContext ec, Type target_type)
1838 if (target_type == TypeManager.sbyte_type)
1839 return new SByteConstant ((sbyte)Value, loc);
1840 if (target_type == TypeManager.byte_type)
1841 return new ByteConstant ((byte)Value, loc);
1842 if (target_type == TypeManager.short_type)
1843 return new ShortConstant ((short)Value, loc);
1844 if (target_type == TypeManager.ushort_type)
1845 return new UShortConstant ((ushort)Value, loc);
1846 if (target_type == TypeManager.int32_type)
1847 return new IntConstant ((int)Value, loc);
1848 if (target_type == TypeManager.uint32_type)
1849 return new UIntConstant ((uint)Value, loc);
1850 if (target_type == TypeManager.int64_type)
1851 return new LongConstant ((long)Value, loc);
1852 if (target_type == TypeManager.uint64_type)
1853 return new ULongConstant ((ulong)Value, loc);
1854 if (target_type == TypeManager.char_type)
1855 return new CharConstant ((char)Value, loc);
1856 if (target_type == TypeManager.float_type)
1857 return new FloatConstant ((float)Value, loc);
1858 if (target_type == TypeManager.double_type)
1859 return new DoubleConstant ((double)Value, loc);
1866 public class StringConstant : Constant {
1867 public readonly string Value;
1869 public StringConstant (string s, Location loc):
1872 type = TypeManager.string_type;
1873 eclass = ExprClass.Value;
1877 // FIXME: Escape the string.
1878 override public string AsString ()
1880 return "\"" + Value + "\"";
1883 public override object GetValue ()
1888 public override void Emit (EmitContext ec)
1891 ec.ig.Emit (OpCodes.Ldnull);
1893 ec.ig.Emit (OpCodes.Ldstr, Value);
1896 public override Constant Increment ()
1898 throw new NotSupportedException ();
1901 public override bool IsDefaultValue {
1903 return Value == null;
1907 public override bool IsNegative {
1913 public override Constant Reduce (EmitContext ec, Type target_type)