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 IsDefaultValue {
169 public abstract bool IsNegative {
174 // Returns true iff 1) the stack type of this is one of Object,
175 // int32, int64 and 2) this == 0 or this == null.
177 public virtual bool IsZeroInteger {
178 get { return false; }
182 public class BoolConstant : Constant {
183 public readonly bool Value;
185 public BoolConstant (bool val)
187 type = TypeManager.bool_type;
188 eclass = ExprClass.Value;
193 override public string AsString ()
195 return Value ? "true" : "false";
198 public override object GetValue ()
200 return (object) Value;
204 public override void Emit (EmitContext ec)
207 ec.ig.Emit (OpCodes.Ldc_I4_1);
209 ec.ig.Emit (OpCodes.Ldc_I4_0);
212 public override bool IsDefaultValue {
218 public override bool IsNegative {
224 public override bool IsZeroInteger {
225 get { return Value == false; }
229 public class ByteConstant : Constant {
230 public readonly byte Value;
232 public ByteConstant (byte v)
234 type = TypeManager.byte_type;
235 eclass = ExprClass.Value;
239 public override void Emit (EmitContext ec)
241 IntLiteral.EmitInt (ec.ig, Value);
244 public override string AsString ()
246 return Value.ToString ();
249 public override object GetValue ()
254 public override DoubleConstant ConvertToDouble ()
256 return new DoubleConstant (Value);
259 public override FloatConstant ConvertToFloat ()
261 return new FloatConstant (Value);
264 public override ULongConstant ConvertToULong ()
266 return new ULongConstant (Value);
269 public override LongConstant ConvertToLong ()
271 return new LongConstant (Value);
274 public override UIntConstant ConvertToUInt ()
276 return new UIntConstant (Value);
279 public override IntConstant ConvertToInt ()
281 return new IntConstant (Value);
284 public override bool IsDefaultValue {
290 public override bool IsNegative {
296 public override bool IsZeroInteger {
297 get { return Value == 0; }
301 public class CharConstant : Constant {
302 public readonly char Value;
304 public CharConstant (char v)
306 type = TypeManager.char_type;
307 eclass = ExprClass.Value;
311 public override void Emit (EmitContext ec)
313 IntLiteral.EmitInt (ec.ig, Value);
316 static public string descape (char c)
342 return c.ToString ();
345 public override string AsString ()
347 return "\"" + descape (Value) + "\"";
350 public override object GetValue ()
355 public override DoubleConstant ConvertToDouble ()
357 return new DoubleConstant (Value);
360 public override FloatConstant ConvertToFloat ()
362 return new FloatConstant (Value);
365 public override ULongConstant ConvertToULong ()
367 return new ULongConstant (Value);
370 public override LongConstant ConvertToLong ()
372 return new LongConstant (Value);
375 public override UIntConstant ConvertToUInt ()
377 return new UIntConstant (Value);
380 public override IntConstant ConvertToInt ()
382 return new IntConstant (Value);
385 public override bool IsDefaultValue {
391 public override bool IsNegative {
397 public override bool IsZeroInteger {
398 get { return Value == '\0'; }
402 public class SByteConstant : Constant {
403 public readonly sbyte Value;
405 public SByteConstant (sbyte v)
407 type = TypeManager.sbyte_type;
408 eclass = ExprClass.Value;
412 public override void Emit (EmitContext ec)
414 IntLiteral.EmitInt (ec.ig, Value);
417 public override string AsString ()
419 return Value.ToString ();
422 public override object GetValue ()
427 public override DoubleConstant ConvertToDouble ()
429 return new DoubleConstant (Value);
432 public override FloatConstant ConvertToFloat ()
434 return new FloatConstant (Value);
437 public override ULongConstant ConvertToULong ()
440 return new ULongConstant ((ulong) Value);
445 public override LongConstant ConvertToLong ()
447 return new LongConstant (Value);
450 public override UIntConstant ConvertToUInt ()
455 public override IntConstant ConvertToInt ()
457 return new IntConstant (Value);
460 public override bool IsDefaultValue {
466 public override bool IsNegative {
472 public override bool IsZeroInteger {
473 get { return Value == 0; }
477 public class ShortConstant : Constant {
478 public readonly short Value;
480 public ShortConstant (short v)
482 type = TypeManager.short_type;
483 eclass = ExprClass.Value;
487 public override void Emit (EmitContext ec)
489 IntLiteral.EmitInt (ec.ig, Value);
492 public override string AsString ()
494 return Value.ToString ();
497 public override object GetValue ()
502 public override DoubleConstant ConvertToDouble ()
504 return new DoubleConstant (Value);
507 public override FloatConstant ConvertToFloat ()
509 return new FloatConstant (Value);
512 public override ULongConstant ConvertToULong ()
517 public override LongConstant ConvertToLong ()
519 return new LongConstant (Value);
522 public override UIntConstant ConvertToUInt ()
527 public override IntConstant ConvertToInt ()
529 return new IntConstant (Value);
532 public override bool IsDefaultValue {
538 public override bool IsZeroInteger {
539 get { return Value == 0; }
542 public override bool IsNegative {
549 public class UShortConstant : Constant {
550 public readonly ushort Value;
552 public UShortConstant (ushort v)
554 type = TypeManager.ushort_type;
555 eclass = ExprClass.Value;
559 public override void Emit (EmitContext ec)
561 IntLiteral.EmitInt (ec.ig, Value);
564 public override string AsString ()
566 return Value.ToString ();
569 public override object GetValue ()
574 public override DoubleConstant ConvertToDouble ()
576 return new DoubleConstant (Value);
579 public override FloatConstant ConvertToFloat ()
581 return new FloatConstant (Value);
584 public override ULongConstant ConvertToULong ()
586 return new ULongConstant (Value);
589 public override LongConstant ConvertToLong ()
591 return new LongConstant (Value);
594 public override UIntConstant ConvertToUInt ()
596 return new UIntConstant (Value);
599 public override IntConstant ConvertToInt ()
601 return new IntConstant (Value);
604 public override bool IsDefaultValue {
610 public override bool IsNegative {
616 public override bool IsZeroInteger {
617 get { return Value == 0; }
621 public class IntConstant : Constant {
622 public readonly int Value;
624 public IntConstant (int v)
626 type = TypeManager.int32_type;
627 eclass = ExprClass.Value;
631 static public void EmitInt (ILGenerator ig, int i)
635 ig.Emit (OpCodes.Ldc_I4_M1);
639 ig.Emit (OpCodes.Ldc_I4_0);
643 ig.Emit (OpCodes.Ldc_I4_1);
647 ig.Emit (OpCodes.Ldc_I4_2);
651 ig.Emit (OpCodes.Ldc_I4_3);
655 ig.Emit (OpCodes.Ldc_I4_4);
659 ig.Emit (OpCodes.Ldc_I4_5);
663 ig.Emit (OpCodes.Ldc_I4_6);
667 ig.Emit (OpCodes.Ldc_I4_7);
671 ig.Emit (OpCodes.Ldc_I4_8);
675 if (i >= -128 && i <= 127){
676 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
678 ig.Emit (OpCodes.Ldc_I4, i);
683 public override void Emit (EmitContext ec)
685 EmitInt (ec.ig, Value);
688 public override string AsString ()
690 return Value.ToString ();
693 public override object GetValue ()
698 public override DecimalConstant ConvertToDecimal()
700 return new DecimalConstant (Value);
703 public override DoubleConstant ConvertToDouble ()
705 return new DoubleConstant (Value);
708 public override FloatConstant ConvertToFloat ()
710 return new FloatConstant (Value);
713 public override ULongConstant ConvertToULong ()
718 return new ULongConstant ((ulong) Value);
721 public override LongConstant ConvertToLong ()
723 return new LongConstant (Value);
726 public override UIntConstant ConvertToUInt ()
731 return new UIntConstant ((uint) Value);
734 public override IntConstant ConvertToInt ()
739 public override bool IsDefaultValue {
745 public override bool IsNegative {
751 public override bool IsZeroInteger {
752 get { return Value == 0; }
756 public class UIntConstant : Constant {
757 public readonly uint Value;
759 public UIntConstant (uint v)
761 type = TypeManager.uint32_type;
762 eclass = ExprClass.Value;
766 public override void Emit (EmitContext ec)
768 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
771 public override string AsString ()
773 return Value.ToString ();
776 public override object GetValue ()
781 public override DoubleConstant ConvertToDouble ()
783 return new DoubleConstant (Value);
786 public override FloatConstant ConvertToFloat ()
788 return new FloatConstant (Value);
791 public override ULongConstant ConvertToULong ()
793 return new ULongConstant (Value);
796 public override LongConstant ConvertToLong ()
798 return new LongConstant (Value);
801 public override UIntConstant ConvertToUInt ()
806 public override IntConstant ConvertToInt ()
811 public override bool IsDefaultValue {
817 public override bool IsNegative {
823 public override bool IsZeroInteger {
824 get { return Value == 0; }
828 public class LongConstant : Constant {
829 public readonly long Value;
831 public LongConstant (long v)
833 type = TypeManager.int64_type;
834 eclass = ExprClass.Value;
838 public override void Emit (EmitContext ec)
840 ILGenerator ig = ec.ig;
842 EmitLong (ig, Value);
845 static public void EmitLong (ILGenerator ig, long l)
848 IntLiteral.EmitInt (ig, unchecked ((int) l));
849 ig.Emit (OpCodes.Conv_U8);
851 ig.Emit (OpCodes.Ldc_I8, l);
855 public override string AsString ()
857 return Value.ToString ();
860 public override object GetValue ()
865 public override DoubleConstant ConvertToDouble ()
867 return new DoubleConstant (Value);
870 public override FloatConstant ConvertToFloat ()
872 return new FloatConstant (Value);
875 public override ULongConstant ConvertToULong ()
880 return new ULongConstant ((ulong) Value);
883 public override LongConstant ConvertToLong ()
888 public override UIntConstant ConvertToUInt ()
893 public override IntConstant ConvertToInt ()
898 public override bool IsDefaultValue {
904 public override bool IsNegative {
910 public override bool IsZeroInteger {
911 get { return Value == 0; }
915 public class ULongConstant : Constant {
916 public readonly ulong Value;
918 public ULongConstant (ulong v)
920 type = TypeManager.uint64_type;
921 eclass = ExprClass.Value;
925 public override void Emit (EmitContext ec)
927 ILGenerator ig = ec.ig;
929 LongLiteral.EmitLong (ig, unchecked ((long) Value));
932 public override string AsString ()
934 return Value.ToString ();
937 public override object GetValue ()
942 public override DoubleConstant ConvertToDouble ()
944 return new DoubleConstant (Value);
947 public override FloatConstant ConvertToFloat ()
949 return new FloatConstant (Value);
952 public override ULongConstant ConvertToULong ()
957 public override LongConstant ConvertToLong ()
962 public override UIntConstant ConvertToUInt ()
967 public override IntConstant ConvertToInt ()
972 public override bool IsDefaultValue {
978 public override bool IsNegative {
984 public override bool IsZeroInteger {
985 get { return Value == 0; }
989 public class FloatConstant : Constant {
990 public readonly float Value;
992 public FloatConstant (float v)
994 type = TypeManager.float_type;
995 eclass = ExprClass.Value;
999 public override void Emit (EmitContext ec)
1001 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1004 public override string AsString ()
1006 return Value.ToString ();
1009 public override object GetValue ()
1014 public override DoubleConstant ConvertToDouble ()
1016 return new DoubleConstant (Value);
1019 public override FloatConstant ConvertToFloat ()
1024 public override LongConstant ConvertToLong ()
1029 public override UIntConstant ConvertToUInt ()
1034 public override IntConstant ConvertToInt ()
1039 public override bool IsDefaultValue {
1045 public override bool IsNegative {
1052 public class DoubleConstant : Constant {
1053 public readonly double Value;
1055 public DoubleConstant (double v)
1057 type = TypeManager.double_type;
1058 eclass = ExprClass.Value;
1062 public override void Emit (EmitContext ec)
1064 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1067 public override string AsString ()
1069 return Value.ToString ();
1072 public override object GetValue ()
1077 public override DoubleConstant ConvertToDouble ()
1082 public override FloatConstant ConvertToFloat ()
1087 public override ULongConstant ConvertToULong ()
1092 public override LongConstant ConvertToLong ()
1097 public override UIntConstant ConvertToUInt ()
1102 public override IntConstant ConvertToInt ()
1107 public override bool IsDefaultValue {
1113 public override bool IsNegative {
1120 public class DecimalConstant : Constant {
1121 public readonly decimal Value;
1123 public DecimalConstant (decimal d)
1125 type = TypeManager.decimal_type;
1126 eclass = ExprClass.Value;
1130 override public string AsString ()
1132 return Value.ToString ();
1135 public override object GetValue ()
1137 return (object) Value;
1140 public override void Emit (EmitContext ec)
1142 ILGenerator ig = ec.ig;
1144 int [] words = Decimal.GetBits (Value);
1145 int power = (words [3] >> 16) & 0xff;
1147 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1149 IntConstant.EmitInt (ig, (int)Value);
1150 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1156 // FIXME: we could optimize this, and call a better
1160 IntConstant.EmitInt (ig, words [0]);
1161 IntConstant.EmitInt (ig, words [1]);
1162 IntConstant.EmitInt (ig, words [2]);
1165 IntConstant.EmitInt (ig, words [3] >> 31);
1168 IntConstant.EmitInt (ig, power);
1170 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1173 public override bool IsDefaultValue {
1179 public override bool IsNegative {
1186 public class StringConstant : Constant {
1187 public readonly string Value;
1189 public StringConstant (string s)
1191 type = TypeManager.string_type;
1192 eclass = ExprClass.Value;
1196 // FIXME: Escape the string.
1197 override public string AsString ()
1199 return "\"" + Value + "\"";
1202 public override object GetValue ()
1207 public override void Emit (EmitContext ec)
1210 ec.ig.Emit (OpCodes.Ldnull);
1212 ec.ig.Emit (OpCodes.Ldstr, Value);
1215 public override bool IsDefaultValue {
1217 return Value == null;
1221 public override bool IsNegative {