2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
11 namespace Mono.CSharp {
14 using System.Reflection.Emit;
17 /// Base class for constants and literals.
19 public abstract class Constant : Expression {
21 /// This is different from ToString in that ToString
22 /// is supposed to be there for debugging purposes,
23 /// and is not guaranteed to be useful for anything else,
24 /// AsString() will provide something that can be used
25 /// for round-tripping C# code. Maybe it can be used
26 /// for IL assembly as well.
28 public abstract string AsString ();
30 override public string ToString ()
32 return this.GetType ().Name + " (" + AsString () + ")";
36 /// This is used to obtain the actual value of the literal
37 /// cast into an object.
39 public abstract object GetValue ();
42 /// Constants are always born in a fully resolved state
44 public override Expression DoResolve (EmitContext ec)
50 // The various ToXXXX conversion functions are used by the constant
51 // folding evaluator. A null value is returned if the conversion is
54 // Note: not all the patterns for catching `implicit_conv' are the same.
55 // some implicit conversions can never be performed between two types
56 // even if the conversion would be lossless (for example short to uint),
57 // but some conversions are explicitly permitted by the standard provided
58 // that there will be no loss of information (for example, int to uint).
60 public DoubleConstant ToDouble (Location loc)
62 DoubleConstant c = ConvertToDouble ();
65 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
70 public FloatConstant ToFloat (Location loc)
72 FloatConstant c = ConvertToFloat ();
75 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
80 public ULongConstant ToULong (Location loc)
82 ULongConstant c = ConvertToULong ();
85 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
90 public LongConstant ToLong (Location loc)
92 LongConstant c = ConvertToLong ();
95 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
100 public UIntConstant ToUInt (Location loc)
102 UIntConstant c = ConvertToUInt ();
105 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
110 public IntConstant ToInt (Location loc)
112 IntConstant c = ConvertToInt ();
115 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
120 public DecimalConstant ToDecimal (Location loc)
122 DecimalConstant c = ConvertToDecimal ();
125 Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
130 public virtual DecimalConstant ConvertToDecimal ()
135 public virtual DoubleConstant ConvertToDouble ()
140 public virtual FloatConstant ConvertToFloat ()
145 public virtual ULongConstant ConvertToULong ()
150 public virtual LongConstant ConvertToLong ()
155 public virtual UIntConstant ConvertToUInt ()
160 public virtual IntConstant ConvertToInt ()
165 public abstract bool IsNegative {
170 // Returns true iff 1) the stack type of this is one of Object,
171 // int32, int64 and 2) this == 0 or this == null.
173 public virtual bool IsZeroInteger {
174 get { return false; }
178 public class BoolConstant : Constant {
179 public readonly bool Value;
181 public BoolConstant (bool val)
183 type = TypeManager.bool_type;
184 eclass = ExprClass.Value;
189 override public string AsString ()
191 return Value ? "true" : "false";
194 public override object GetValue ()
196 return (object) Value;
200 public override void Emit (EmitContext ec)
203 ec.ig.Emit (OpCodes.Ldc_I4_1);
205 ec.ig.Emit (OpCodes.Ldc_I4_0);
208 public override bool IsNegative {
214 public override bool IsZeroInteger {
215 get { return Value == false; }
219 public class ByteConstant : Constant {
220 public readonly byte Value;
222 public ByteConstant (byte v)
224 type = TypeManager.byte_type;
225 eclass = ExprClass.Value;
229 public override void Emit (EmitContext ec)
231 IntLiteral.EmitInt (ec.ig, Value);
234 public override string AsString ()
236 return Value.ToString ();
239 public override object GetValue ()
244 public override DoubleConstant ConvertToDouble ()
246 return new DoubleConstant (Value);
249 public override FloatConstant ConvertToFloat ()
251 return new FloatConstant (Value);
254 public override ULongConstant ConvertToULong ()
256 return new ULongConstant (Value);
259 public override LongConstant ConvertToLong ()
261 return new LongConstant (Value);
264 public override UIntConstant ConvertToUInt ()
266 return new UIntConstant (Value);
269 public override IntConstant ConvertToInt ()
271 return new IntConstant (Value);
274 public override bool IsNegative {
280 public override bool IsZeroInteger {
281 get { return Value == 0; }
285 public class CharConstant : Constant {
286 public readonly char Value;
288 public CharConstant (char v)
290 type = TypeManager.char_type;
291 eclass = ExprClass.Value;
295 public override void Emit (EmitContext ec)
297 IntLiteral.EmitInt (ec.ig, Value);
300 static public string descape (char c)
326 return c.ToString ();
329 public override string AsString ()
331 return "\"" + descape (Value) + "\"";
334 public override object GetValue ()
339 public override DoubleConstant ConvertToDouble ()
341 return new DoubleConstant (Value);
344 public override FloatConstant ConvertToFloat ()
346 return new FloatConstant (Value);
349 public override ULongConstant ConvertToULong ()
351 return new ULongConstant (Value);
354 public override LongConstant ConvertToLong ()
356 return new LongConstant (Value);
359 public override UIntConstant ConvertToUInt ()
361 return new UIntConstant (Value);
364 public override IntConstant ConvertToInt ()
366 return new IntConstant (Value);
369 public override bool IsNegative {
375 public override bool IsZeroInteger {
376 get { return Value == '\0'; }
380 public class SByteConstant : Constant {
381 public readonly sbyte Value;
383 public SByteConstant (sbyte v)
385 type = TypeManager.sbyte_type;
386 eclass = ExprClass.Value;
390 public override void Emit (EmitContext ec)
392 IntLiteral.EmitInt (ec.ig, Value);
395 public override string AsString ()
397 return Value.ToString ();
400 public override object GetValue ()
405 public override DoubleConstant ConvertToDouble ()
407 return new DoubleConstant (Value);
410 public override FloatConstant ConvertToFloat ()
412 return new FloatConstant (Value);
415 public override ULongConstant ConvertToULong ()
418 return new ULongConstant ((ulong) Value);
423 public override LongConstant ConvertToLong ()
425 return new LongConstant (Value);
428 public override UIntConstant ConvertToUInt ()
433 public override IntConstant ConvertToInt ()
435 return new IntConstant (Value);
438 public override bool IsNegative {
444 public override bool IsZeroInteger {
445 get { return Value == 0; }
449 public class ShortConstant : Constant {
450 public readonly short Value;
452 public ShortConstant (short v)
454 type = TypeManager.short_type;
455 eclass = ExprClass.Value;
459 public override void Emit (EmitContext ec)
461 IntLiteral.EmitInt (ec.ig, Value);
464 public override string AsString ()
466 return Value.ToString ();
469 public override object GetValue ()
474 public override DoubleConstant ConvertToDouble ()
476 return new DoubleConstant (Value);
479 public override FloatConstant ConvertToFloat ()
481 return new FloatConstant (Value);
484 public override ULongConstant ConvertToULong ()
489 public override LongConstant ConvertToLong ()
491 return new LongConstant (Value);
494 public override UIntConstant ConvertToUInt ()
499 public override IntConstant ConvertToInt ()
501 return new IntConstant (Value);
504 public override bool IsZeroInteger {
505 get { return Value == 0; }
508 public override bool IsNegative {
515 public class UShortConstant : Constant {
516 public readonly ushort Value;
518 public UShortConstant (ushort v)
520 type = TypeManager.ushort_type;
521 eclass = ExprClass.Value;
525 public override void Emit (EmitContext ec)
527 IntLiteral.EmitInt (ec.ig, Value);
530 public override string AsString ()
532 return Value.ToString ();
535 public override object GetValue ()
540 public override DoubleConstant ConvertToDouble ()
542 return new DoubleConstant (Value);
545 public override FloatConstant ConvertToFloat ()
547 return new FloatConstant (Value);
550 public override ULongConstant ConvertToULong ()
552 return new ULongConstant (Value);
555 public override LongConstant ConvertToLong ()
557 return new LongConstant (Value);
560 public override UIntConstant ConvertToUInt ()
562 return new UIntConstant (Value);
565 public override IntConstant ConvertToInt ()
567 return new IntConstant (Value);
570 public override bool IsNegative {
576 public override bool IsZeroInteger {
577 get { return Value == 0; }
581 public class IntConstant : Constant {
582 public readonly int Value;
584 public IntConstant (int v)
586 type = TypeManager.int32_type;
587 eclass = ExprClass.Value;
591 static public void EmitInt (ILGenerator ig, int i)
595 ig.Emit (OpCodes.Ldc_I4_M1);
599 ig.Emit (OpCodes.Ldc_I4_0);
603 ig.Emit (OpCodes.Ldc_I4_1);
607 ig.Emit (OpCodes.Ldc_I4_2);
611 ig.Emit (OpCodes.Ldc_I4_3);
615 ig.Emit (OpCodes.Ldc_I4_4);
619 ig.Emit (OpCodes.Ldc_I4_5);
623 ig.Emit (OpCodes.Ldc_I4_6);
627 ig.Emit (OpCodes.Ldc_I4_7);
631 ig.Emit (OpCodes.Ldc_I4_8);
635 if (i >= -128 && i <= 127){
636 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
638 ig.Emit (OpCodes.Ldc_I4, i);
643 public override void Emit (EmitContext ec)
645 EmitInt (ec.ig, Value);
648 public override string AsString ()
650 return Value.ToString ();
653 public override object GetValue ()
658 public override DecimalConstant ConvertToDecimal()
660 return new DecimalConstant (Value);
663 public override DoubleConstant ConvertToDouble ()
665 return new DoubleConstant (Value);
668 public override FloatConstant ConvertToFloat ()
670 return new FloatConstant (Value);
673 public override ULongConstant ConvertToULong ()
678 return new ULongConstant ((ulong) Value);
681 public override LongConstant ConvertToLong ()
683 return new LongConstant (Value);
686 public override UIntConstant ConvertToUInt ()
691 return new UIntConstant ((uint) Value);
694 public override IntConstant ConvertToInt ()
699 public override bool IsNegative {
705 public override bool IsZeroInteger {
706 get { return Value == 0; }
710 public class UIntConstant : Constant {
711 public readonly uint Value;
713 public UIntConstant (uint v)
715 type = TypeManager.uint32_type;
716 eclass = ExprClass.Value;
720 public override void Emit (EmitContext ec)
722 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
725 public override string AsString ()
727 return Value.ToString ();
730 public override object GetValue ()
735 public override DoubleConstant ConvertToDouble ()
737 return new DoubleConstant (Value);
740 public override FloatConstant ConvertToFloat ()
742 return new FloatConstant (Value);
745 public override ULongConstant ConvertToULong ()
747 return new ULongConstant (Value);
750 public override LongConstant ConvertToLong ()
752 return new LongConstant (Value);
755 public override UIntConstant ConvertToUInt ()
760 public override IntConstant ConvertToInt ()
765 public override bool IsNegative {
771 public override bool IsZeroInteger {
772 get { return Value == 0; }
776 public class LongConstant : Constant {
777 public readonly long Value;
779 public LongConstant (long v)
781 type = TypeManager.int64_type;
782 eclass = ExprClass.Value;
786 public override void Emit (EmitContext ec)
788 ILGenerator ig = ec.ig;
790 EmitLong (ig, Value);
793 static public void EmitLong (ILGenerator ig, long l)
796 IntLiteral.EmitInt (ig, unchecked ((int) l));
797 ig.Emit (OpCodes.Conv_U8);
799 ig.Emit (OpCodes.Ldc_I8, l);
803 public override string AsString ()
805 return Value.ToString ();
808 public override object GetValue ()
813 public override DoubleConstant ConvertToDouble ()
815 return new DoubleConstant (Value);
818 public override FloatConstant ConvertToFloat ()
820 return new FloatConstant (Value);
823 public override ULongConstant ConvertToULong ()
828 return new ULongConstant ((ulong) Value);
831 public override LongConstant ConvertToLong ()
836 public override UIntConstant ConvertToUInt ()
841 public override IntConstant ConvertToInt ()
846 public override bool IsNegative {
852 public override bool IsZeroInteger {
853 get { return Value == 0; }
857 public class ULongConstant : Constant {
858 public readonly ulong Value;
860 public ULongConstant (ulong v)
862 type = TypeManager.uint64_type;
863 eclass = ExprClass.Value;
867 public override void Emit (EmitContext ec)
869 ILGenerator ig = ec.ig;
871 LongLiteral.EmitLong (ig, unchecked ((long) Value));
874 public override string AsString ()
876 return Value.ToString ();
879 public override object GetValue ()
884 public override DoubleConstant ConvertToDouble ()
886 return new DoubleConstant (Value);
889 public override FloatConstant ConvertToFloat ()
891 return new FloatConstant (Value);
894 public override ULongConstant ConvertToULong ()
899 public override LongConstant ConvertToLong ()
904 public override UIntConstant ConvertToUInt ()
909 public override IntConstant ConvertToInt ()
914 public override bool IsNegative {
920 public override bool IsZeroInteger {
921 get { return Value == 0; }
925 public class FloatConstant : Constant {
926 public readonly float Value;
928 public FloatConstant (float v)
930 type = TypeManager.float_type;
931 eclass = ExprClass.Value;
935 public override void Emit (EmitContext ec)
937 ec.ig.Emit (OpCodes.Ldc_R4, Value);
940 public override string AsString ()
942 return Value.ToString ();
945 public override object GetValue ()
950 public override DoubleConstant ConvertToDouble ()
952 return new DoubleConstant (Value);
955 public override FloatConstant ConvertToFloat ()
960 public override LongConstant ConvertToLong ()
965 public override UIntConstant ConvertToUInt ()
970 public override IntConstant ConvertToInt ()
975 public override bool IsNegative {
982 public class DoubleConstant : Constant {
983 public readonly double Value;
985 public DoubleConstant (double v)
987 type = TypeManager.double_type;
988 eclass = ExprClass.Value;
992 public override void Emit (EmitContext ec)
994 ec.ig.Emit (OpCodes.Ldc_R8, Value);
997 public override string AsString ()
999 return Value.ToString ();
1002 public override object GetValue ()
1007 public override DoubleConstant ConvertToDouble ()
1012 public override FloatConstant ConvertToFloat ()
1017 public override ULongConstant ConvertToULong ()
1022 public override LongConstant ConvertToLong ()
1027 public override UIntConstant ConvertToUInt ()
1032 public override IntConstant ConvertToInt ()
1037 public override bool IsNegative {
1044 public class DecimalConstant : Constant {
1045 public readonly decimal Value;
1047 public DecimalConstant (decimal d)
1049 type = TypeManager.decimal_type;
1050 eclass = ExprClass.Value;
1054 override public string AsString ()
1056 return Value.ToString ();
1059 public override object GetValue ()
1061 return (object) Value;
1064 public override void Emit (EmitContext ec)
1066 ILGenerator ig = ec.ig;
1068 int [] words = Decimal.GetBits (Value);
1069 int power = (words [3] >> 16) & 0xff;
1071 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1073 IntConstant.EmitInt (ig, (int)Value);
1074 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1080 // FIXME: we could optimize this, and call a better
1084 IntConstant.EmitInt (ig, words [0]);
1085 IntConstant.EmitInt (ig, words [1]);
1086 IntConstant.EmitInt (ig, words [2]);
1089 IntConstant.EmitInt (ig, words [3] >> 31);
1092 IntConstant.EmitInt (ig, power);
1094 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1097 public override bool IsNegative {
1104 public class StringConstant : Constant {
1105 public readonly string Value;
1107 public StringConstant (string s)
1109 type = TypeManager.string_type;
1110 eclass = ExprClass.Value;
1114 // FIXME: Escape the string.
1115 override public string AsString ()
1117 return "\"" + Value + "\"";
1120 public override object GetValue ()
1125 public override void Emit (EmitContext ec)
1128 ec.ig.Emit (OpCodes.Ldnull);
1130 ec.ig.Emit (OpCodes.Ldstr, Value);
1133 public override bool IsNegative {