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)
49 public virtual void Error_ConstantValueCannotBeConverted (Location loc, Type t)
51 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
52 AsString (), TypeManager.CSharpName (t));
57 // The various ToXXXX conversion functions are used by the constant
58 // folding evaluator. A null value is returned if the conversion is
61 // Note: not all the patterns for catching `implicit_conv' are the same.
62 // some implicit conversions can never be performed between two types
63 // even if the conversion would be lossless (for example short to uint),
64 // but some conversions are explicitly permitted by the standard provided
65 // that there will be no loss of information (for example, int to uint).
67 public DoubleConstant ToDouble (Location loc)
69 DoubleConstant c = ConvertToDouble ();
72 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
77 public FloatConstant ToFloat (Location loc)
79 FloatConstant c = ConvertToFloat ();
82 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
87 public ULongConstant ToULong (Location loc)
89 ULongConstant c = ConvertToULong ();
92 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
97 public LongConstant ToLong (Location loc)
99 LongConstant c = ConvertToLong ();
102 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
107 public UIntConstant ToUInt (Location loc)
109 UIntConstant c = ConvertToUInt ();
112 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
117 public IntConstant ToInt (Location loc)
119 IntConstant c = ConvertToInt ();
122 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
127 public DecimalConstant ToDecimal (Location loc)
129 DecimalConstant c = ConvertToDecimal ();
132 Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
137 public virtual DecimalConstant ConvertToDecimal ()
142 public virtual DoubleConstant ConvertToDouble ()
147 public virtual FloatConstant ConvertToFloat ()
152 public virtual ULongConstant ConvertToULong ()
157 public virtual LongConstant ConvertToLong ()
162 public virtual UIntConstant ConvertToUInt ()
167 public virtual IntConstant ConvertToInt ()
172 public abstract bool IsDefaultValue {
176 public abstract bool IsNegative {
181 // Returns true iff 1) the stack type of this is one of Object,
182 // int32, int64 and 2) this == 0 or this == null.
184 public virtual bool IsZeroInteger {
185 get { return false; }
189 public class BoolConstant : Constant {
190 public readonly bool Value;
192 public BoolConstant (bool val)
194 type = TypeManager.bool_type;
195 eclass = ExprClass.Value;
200 override public string AsString ()
202 return Value ? "true" : "false";
205 public override object GetValue ()
207 return (object) Value;
211 public override void Emit (EmitContext ec)
214 ec.ig.Emit (OpCodes.Ldc_I4_1);
216 ec.ig.Emit (OpCodes.Ldc_I4_0);
219 public override bool IsDefaultValue {
225 public override bool IsNegative {
231 public override bool IsZeroInteger {
232 get { return Value == false; }
236 public class ByteConstant : Constant {
237 public readonly byte Value;
239 public ByteConstant (byte v)
241 type = TypeManager.byte_type;
242 eclass = ExprClass.Value;
246 public override void Emit (EmitContext ec)
248 IntLiteral.EmitInt (ec.ig, Value);
251 public override string AsString ()
253 return Value.ToString ();
256 public override object GetValue ()
261 public override DoubleConstant ConvertToDouble ()
263 return new DoubleConstant (Value);
266 public override FloatConstant ConvertToFloat ()
268 return new FloatConstant (Value);
271 public override ULongConstant ConvertToULong ()
273 return new ULongConstant (Value);
276 public override LongConstant ConvertToLong ()
278 return new LongConstant (Value);
281 public override UIntConstant ConvertToUInt ()
283 return new UIntConstant (Value);
286 public override IntConstant ConvertToInt ()
288 return new IntConstant (Value);
291 public override bool IsDefaultValue {
297 public override bool IsNegative {
303 public override bool IsZeroInteger {
304 get { return Value == 0; }
308 public class CharConstant : Constant {
309 public readonly char Value;
311 public CharConstant (char v)
313 type = TypeManager.char_type;
314 eclass = ExprClass.Value;
318 public override void Emit (EmitContext ec)
320 IntLiteral.EmitInt (ec.ig, Value);
323 static public string descape (char c)
349 return c.ToString ();
352 public override string AsString ()
354 return "\"" + descape (Value) + "\"";
357 public override object GetValue ()
362 public override DoubleConstant ConvertToDouble ()
364 return new DoubleConstant (Value);
367 public override FloatConstant ConvertToFloat ()
369 return new FloatConstant (Value);
372 public override ULongConstant ConvertToULong ()
374 return new ULongConstant (Value);
377 public override LongConstant ConvertToLong ()
379 return new LongConstant (Value);
382 public override UIntConstant ConvertToUInt ()
384 return new UIntConstant (Value);
387 public override IntConstant ConvertToInt ()
389 return new IntConstant (Value);
392 public override bool IsDefaultValue {
398 public override bool IsNegative {
404 public override bool IsZeroInteger {
405 get { return Value == '\0'; }
409 public class SByteConstant : Constant {
410 public readonly sbyte Value;
412 public SByteConstant (sbyte v)
414 type = TypeManager.sbyte_type;
415 eclass = ExprClass.Value;
419 public override void Emit (EmitContext ec)
421 IntLiteral.EmitInt (ec.ig, Value);
424 public override string AsString ()
426 return Value.ToString ();
429 public override object GetValue ()
434 public override DoubleConstant ConvertToDouble ()
436 return new DoubleConstant (Value);
439 public override FloatConstant ConvertToFloat ()
441 return new FloatConstant (Value);
444 public override ULongConstant ConvertToULong ()
447 return new ULongConstant ((ulong) Value);
452 public override LongConstant ConvertToLong ()
454 return new LongConstant (Value);
457 public override UIntConstant ConvertToUInt ()
462 public override IntConstant ConvertToInt ()
464 return new IntConstant (Value);
467 public override bool IsDefaultValue {
473 public override bool IsNegative {
479 public override bool IsZeroInteger {
480 get { return Value == 0; }
484 public class ShortConstant : Constant {
485 public readonly short Value;
487 public ShortConstant (short v)
489 type = TypeManager.short_type;
490 eclass = ExprClass.Value;
494 public override void Emit (EmitContext ec)
496 IntLiteral.EmitInt (ec.ig, Value);
499 public override string AsString ()
501 return Value.ToString ();
504 public override object GetValue ()
509 public override DoubleConstant ConvertToDouble ()
511 return new DoubleConstant (Value);
514 public override FloatConstant ConvertToFloat ()
516 return new FloatConstant (Value);
519 public override ULongConstant ConvertToULong ()
524 public override LongConstant ConvertToLong ()
526 return new LongConstant (Value);
529 public override UIntConstant ConvertToUInt ()
534 public override IntConstant ConvertToInt ()
536 return new IntConstant (Value);
539 public override bool IsDefaultValue {
545 public override bool IsZeroInteger {
546 get { return Value == 0; }
549 public override bool IsNegative {
556 public class UShortConstant : Constant {
557 public readonly ushort Value;
559 public UShortConstant (ushort v)
561 type = TypeManager.ushort_type;
562 eclass = ExprClass.Value;
566 public override void Emit (EmitContext ec)
568 IntLiteral.EmitInt (ec.ig, Value);
571 public override string AsString ()
573 return Value.ToString ();
576 public override object GetValue ()
581 public override DoubleConstant ConvertToDouble ()
583 return new DoubleConstant (Value);
586 public override FloatConstant ConvertToFloat ()
588 return new FloatConstant (Value);
591 public override ULongConstant ConvertToULong ()
593 return new ULongConstant (Value);
596 public override LongConstant ConvertToLong ()
598 return new LongConstant (Value);
601 public override UIntConstant ConvertToUInt ()
603 return new UIntConstant (Value);
606 public override IntConstant ConvertToInt ()
608 return new IntConstant (Value);
611 public override bool IsDefaultValue {
617 public override bool IsNegative {
623 public override bool IsZeroInteger {
624 get { return Value == 0; }
628 public class IntConstant : Constant {
629 public readonly int Value;
631 public IntConstant (int v)
633 type = TypeManager.int32_type;
634 eclass = ExprClass.Value;
638 static public void EmitInt (ILGenerator ig, int i)
642 ig.Emit (OpCodes.Ldc_I4_M1);
646 ig.Emit (OpCodes.Ldc_I4_0);
650 ig.Emit (OpCodes.Ldc_I4_1);
654 ig.Emit (OpCodes.Ldc_I4_2);
658 ig.Emit (OpCodes.Ldc_I4_3);
662 ig.Emit (OpCodes.Ldc_I4_4);
666 ig.Emit (OpCodes.Ldc_I4_5);
670 ig.Emit (OpCodes.Ldc_I4_6);
674 ig.Emit (OpCodes.Ldc_I4_7);
678 ig.Emit (OpCodes.Ldc_I4_8);
682 if (i >= -128 && i <= 127){
683 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
685 ig.Emit (OpCodes.Ldc_I4, i);
690 public override void Emit (EmitContext ec)
692 EmitInt (ec.ig, Value);
695 public override string AsString ()
697 return Value.ToString ();
700 public override object GetValue ()
705 public override DecimalConstant ConvertToDecimal()
707 return new DecimalConstant (Value);
710 public override DoubleConstant ConvertToDouble ()
712 return new DoubleConstant (Value);
715 public override FloatConstant ConvertToFloat ()
717 return new FloatConstant (Value);
720 public override ULongConstant ConvertToULong ()
725 return new ULongConstant ((ulong) Value);
728 public override LongConstant ConvertToLong ()
730 return new LongConstant (Value);
733 public override UIntConstant ConvertToUInt ()
738 return new UIntConstant ((uint) Value);
741 public override IntConstant ConvertToInt ()
746 public override bool IsDefaultValue {
752 public override bool IsNegative {
758 public override bool IsZeroInteger {
759 get { return Value == 0; }
763 public class UIntConstant : Constant {
764 public readonly uint Value;
766 public UIntConstant (uint v)
768 type = TypeManager.uint32_type;
769 eclass = ExprClass.Value;
773 public override void Emit (EmitContext ec)
775 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
778 public override string AsString ()
780 return Value.ToString ();
783 public override object GetValue ()
788 public override DoubleConstant ConvertToDouble ()
790 return new DoubleConstant (Value);
793 public override FloatConstant ConvertToFloat ()
795 return new FloatConstant (Value);
798 public override ULongConstant ConvertToULong ()
800 return new ULongConstant (Value);
803 public override LongConstant ConvertToLong ()
805 return new LongConstant (Value);
808 public override UIntConstant ConvertToUInt ()
813 public override IntConstant ConvertToInt ()
818 public override bool IsDefaultValue {
824 public override bool IsNegative {
830 public override bool IsZeroInteger {
831 get { return Value == 0; }
835 public class LongConstant : Constant {
836 public readonly long Value;
838 public LongConstant (long v)
840 type = TypeManager.int64_type;
841 eclass = ExprClass.Value;
845 public override void Emit (EmitContext ec)
847 ILGenerator ig = ec.ig;
849 EmitLong (ig, Value);
852 static public void EmitLong (ILGenerator ig, long l)
855 IntLiteral.EmitInt (ig, unchecked ((int) l));
856 ig.Emit (OpCodes.Conv_U8);
858 ig.Emit (OpCodes.Ldc_I8, l);
862 public override string AsString ()
864 return Value.ToString ();
867 public override object GetValue ()
872 public override DoubleConstant ConvertToDouble ()
874 return new DoubleConstant (Value);
877 public override FloatConstant ConvertToFloat ()
879 return new FloatConstant (Value);
882 public override ULongConstant ConvertToULong ()
887 return new ULongConstant ((ulong) Value);
890 public override LongConstant ConvertToLong ()
895 public override UIntConstant ConvertToUInt ()
900 public override IntConstant ConvertToInt ()
905 public override bool IsDefaultValue {
911 public override bool IsNegative {
917 public override bool IsZeroInteger {
918 get { return Value == 0; }
922 public class ULongConstant : Constant {
923 public readonly ulong Value;
925 public ULongConstant (ulong v)
927 type = TypeManager.uint64_type;
928 eclass = ExprClass.Value;
932 public override void Emit (EmitContext ec)
934 ILGenerator ig = ec.ig;
936 LongLiteral.EmitLong (ig, unchecked ((long) Value));
939 public override string AsString ()
941 return Value.ToString ();
944 public override object GetValue ()
949 public override DoubleConstant ConvertToDouble ()
951 return new DoubleConstant (Value);
954 public override FloatConstant ConvertToFloat ()
956 return new FloatConstant (Value);
959 public override ULongConstant ConvertToULong ()
964 public override LongConstant ConvertToLong ()
969 public override UIntConstant ConvertToUInt ()
974 public override IntConstant ConvertToInt ()
979 public override bool IsDefaultValue {
985 public override bool IsNegative {
991 public override bool IsZeroInteger {
992 get { return Value == 0; }
996 public class FloatConstant : Constant {
997 public readonly float Value;
999 public FloatConstant (float v)
1001 type = TypeManager.float_type;
1002 eclass = ExprClass.Value;
1006 public override void Emit (EmitContext ec)
1008 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1011 public override string AsString ()
1013 return Value.ToString ();
1016 public override object GetValue ()
1021 public override DoubleConstant ConvertToDouble ()
1023 return new DoubleConstant (Value);
1026 public override FloatConstant ConvertToFloat ()
1031 public override LongConstant ConvertToLong ()
1036 public override UIntConstant ConvertToUInt ()
1041 public override IntConstant ConvertToInt ()
1046 public override bool IsDefaultValue {
1052 public override bool IsNegative {
1059 public class DoubleConstant : Constant {
1060 public readonly double Value;
1062 public DoubleConstant (double v)
1064 type = TypeManager.double_type;
1065 eclass = ExprClass.Value;
1069 public override void Emit (EmitContext ec)
1071 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1074 public override string AsString ()
1076 return Value.ToString ();
1079 public override object GetValue ()
1084 public override DoubleConstant ConvertToDouble ()
1089 public override FloatConstant ConvertToFloat ()
1094 public override ULongConstant ConvertToULong ()
1099 public override LongConstant ConvertToLong ()
1104 public override UIntConstant ConvertToUInt ()
1109 public override IntConstant ConvertToInt ()
1114 public override bool IsDefaultValue {
1120 public override bool IsNegative {
1127 public class DecimalConstant : Constant {
1128 public readonly decimal Value;
1130 public DecimalConstant (decimal d)
1132 type = TypeManager.decimal_type;
1133 eclass = ExprClass.Value;
1137 override public string AsString ()
1139 return Value.ToString ();
1142 public override object GetValue ()
1144 return (object) Value;
1147 public override void Emit (EmitContext ec)
1149 ILGenerator ig = ec.ig;
1151 int [] words = Decimal.GetBits (Value);
1152 int power = (words [3] >> 16) & 0xff;
1154 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1156 IntConstant.EmitInt (ig, (int)Value);
1157 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1163 // FIXME: we could optimize this, and call a better
1167 IntConstant.EmitInt (ig, words [0]);
1168 IntConstant.EmitInt (ig, words [1]);
1169 IntConstant.EmitInt (ig, words [2]);
1172 IntConstant.EmitInt (ig, words [3] >> 31);
1175 IntConstant.EmitInt (ig, power);
1177 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1180 public override bool IsDefaultValue {
1186 public override bool IsNegative {
1193 public class StringConstant : Constant {
1194 public readonly string Value;
1196 public StringConstant (string s)
1198 type = TypeManager.string_type;
1199 eclass = ExprClass.Value;
1203 // FIXME: Escape the string.
1204 override public string AsString ()
1206 return "\"" + Value + "\"";
1209 public override object GetValue ()
1214 public override void Emit (EmitContext ec)
1217 ec.ig.Emit (OpCodes.Ldnull);
1219 ec.ig.Emit (OpCodes.Ldstr, Value);
1222 public override bool IsDefaultValue {
1224 return Value == null;
1228 public override bool IsNegative {