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 virtual DoubleConstant
ConvertToDouble ()
125 public virtual FloatConstant
ConvertToFloat ()
130 public virtual ULongConstant
ConvertToULong ()
135 public virtual LongConstant
ConvertToLong ()
140 public virtual UIntConstant
ConvertToUInt ()
145 public virtual IntConstant
ConvertToInt ()
150 public abstract bool IsNegative
{
155 // Returns true iff 1) the stack type of this is one of Object,
156 // int32, int64 and 2) this == 0 or this == null.
158 public virtual bool IsZeroInteger
{
159 get { return false; }
163 public class BoolConstant
: Constant
{
164 public readonly bool Value
;
166 public BoolConstant (bool val
)
168 type
= TypeManager
.bool_type
;
169 eclass
= ExprClass
.Value
;
174 override public string AsString ()
176 return Value
? "true" : "false";
179 public override object GetValue ()
181 return (object) Value
;
185 public override void Emit (EmitContext ec
)
188 ec
.ig
.Emit (OpCodes
.Ldc_I4_1
);
190 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
193 public override bool IsNegative
{
199 public override bool IsZeroInteger
{
200 get { return Value == false; }
204 public class ByteConstant
: Constant
{
205 public readonly byte Value
;
207 public ByteConstant (byte v
)
209 type
= TypeManager
.byte_type
;
210 eclass
= ExprClass
.Value
;
214 public override void Emit (EmitContext ec
)
216 IntLiteral
.EmitInt (ec
.ig
, Value
);
219 public override string AsString ()
221 return Value
.ToString ();
224 public override object GetValue ()
229 public override DoubleConstant
ConvertToDouble ()
231 return new DoubleConstant (Value
);
234 public override FloatConstant
ConvertToFloat ()
236 return new FloatConstant (Value
);
239 public override ULongConstant
ConvertToULong ()
241 return new ULongConstant (Value
);
244 public override LongConstant
ConvertToLong ()
246 return new LongConstant (Value
);
249 public override UIntConstant
ConvertToUInt ()
251 return new UIntConstant (Value
);
254 public override IntConstant
ConvertToInt ()
256 return new IntConstant (Value
);
259 public override bool IsNegative
{
265 public override bool IsZeroInteger
{
266 get { return Value == 0; }
270 public class CharConstant
: Constant
{
271 public readonly char Value
;
273 public CharConstant (char v
)
275 type
= TypeManager
.char_type
;
276 eclass
= ExprClass
.Value
;
280 public override void Emit (EmitContext ec
)
282 IntLiteral
.EmitInt (ec
.ig
, Value
);
285 static public string descape (char c
)
311 return c
.ToString ();
314 public override string AsString ()
316 return "\"" + descape (Value
) + "\"";
319 public override object GetValue ()
324 public override DoubleConstant
ConvertToDouble ()
326 return new DoubleConstant (Value
);
329 public override FloatConstant
ConvertToFloat ()
331 return new FloatConstant (Value
);
334 public override ULongConstant
ConvertToULong ()
336 return new ULongConstant (Value
);
339 public override LongConstant
ConvertToLong ()
341 return new LongConstant (Value
);
344 public override UIntConstant
ConvertToUInt ()
346 return new UIntConstant (Value
);
349 public override IntConstant
ConvertToInt ()
351 return new IntConstant (Value
);
354 public override bool IsNegative
{
360 public override bool IsZeroInteger
{
361 get { return Value == '\0'; }
365 public class SByteConstant
: Constant
{
366 public readonly sbyte Value
;
368 public SByteConstant (sbyte v
)
370 type
= TypeManager
.sbyte_type
;
371 eclass
= ExprClass
.Value
;
375 public override void Emit (EmitContext ec
)
377 IntLiteral
.EmitInt (ec
.ig
, Value
);
380 public override string AsString ()
382 return Value
.ToString ();
385 public override object GetValue ()
390 public override DoubleConstant
ConvertToDouble ()
392 return new DoubleConstant (Value
);
395 public override FloatConstant
ConvertToFloat ()
397 return new FloatConstant (Value
);
400 public override ULongConstant
ConvertToULong ()
403 return new ULongConstant ((ulong) Value
);
408 public override LongConstant
ConvertToLong ()
410 return new LongConstant (Value
);
413 public override UIntConstant
ConvertToUInt ()
418 public override IntConstant
ConvertToInt ()
420 return new IntConstant (Value
);
423 public override bool IsNegative
{
429 public override bool IsZeroInteger
{
430 get { return Value == 0; }
434 public class ShortConstant
: Constant
{
435 public readonly short Value
;
437 public ShortConstant (short v
)
439 type
= TypeManager
.short_type
;
440 eclass
= ExprClass
.Value
;
444 public override void Emit (EmitContext ec
)
446 IntLiteral
.EmitInt (ec
.ig
, Value
);
449 public override string AsString ()
451 return Value
.ToString ();
454 public override object GetValue ()
459 public override DoubleConstant
ConvertToDouble ()
461 return new DoubleConstant (Value
);
464 public override FloatConstant
ConvertToFloat ()
466 return new FloatConstant (Value
);
469 public override ULongConstant
ConvertToULong ()
474 public override LongConstant
ConvertToLong ()
476 return new LongConstant (Value
);
479 public override UIntConstant
ConvertToUInt ()
484 public override IntConstant
ConvertToInt ()
486 return new IntConstant (Value
);
489 public override bool IsZeroInteger
{
490 get { return Value == 0; }
493 public override bool IsNegative
{
500 public class UShortConstant
: Constant
{
501 public readonly ushort Value
;
503 public UShortConstant (ushort v
)
505 type
= TypeManager
.ushort_type
;
506 eclass
= ExprClass
.Value
;
510 public override void Emit (EmitContext ec
)
512 IntLiteral
.EmitInt (ec
.ig
, Value
);
515 public override string AsString ()
517 return Value
.ToString ();
520 public override object GetValue ()
525 public override DoubleConstant
ConvertToDouble ()
527 return new DoubleConstant (Value
);
530 public override FloatConstant
ConvertToFloat ()
532 return new FloatConstant (Value
);
535 public override ULongConstant
ConvertToULong ()
537 return new ULongConstant (Value
);
540 public override LongConstant
ConvertToLong ()
542 return new LongConstant (Value
);
545 public override UIntConstant
ConvertToUInt ()
547 return new UIntConstant (Value
);
550 public override IntConstant
ConvertToInt ()
552 return new IntConstant (Value
);
555 public override bool IsNegative
{
561 public override bool IsZeroInteger
{
562 get { return Value == 0; }
566 public class IntConstant
: Constant
{
567 public readonly int Value
;
569 public IntConstant (int v
)
571 type
= TypeManager
.int32_type
;
572 eclass
= ExprClass
.Value
;
576 static public void EmitInt (ILGenerator ig
, int i
)
580 ig
.Emit (OpCodes
.Ldc_I4_M1
);
584 ig
.Emit (OpCodes
.Ldc_I4_0
);
588 ig
.Emit (OpCodes
.Ldc_I4_1
);
592 ig
.Emit (OpCodes
.Ldc_I4_2
);
596 ig
.Emit (OpCodes
.Ldc_I4_3
);
600 ig
.Emit (OpCodes
.Ldc_I4_4
);
604 ig
.Emit (OpCodes
.Ldc_I4_5
);
608 ig
.Emit (OpCodes
.Ldc_I4_6
);
612 ig
.Emit (OpCodes
.Ldc_I4_7
);
616 ig
.Emit (OpCodes
.Ldc_I4_8
);
620 if (i
>= -128 && i
<= 127){
621 ig
.Emit (OpCodes
.Ldc_I4_S
, (sbyte) i
);
623 ig
.Emit (OpCodes
.Ldc_I4
, i
);
628 public override void Emit (EmitContext ec
)
630 EmitInt (ec
.ig
, Value
);
633 public override string AsString ()
635 return Value
.ToString ();
638 public override object GetValue ()
643 public override DoubleConstant
ConvertToDouble ()
645 return new DoubleConstant (Value
);
648 public override FloatConstant
ConvertToFloat ()
650 return new FloatConstant (Value
);
653 public override ULongConstant
ConvertToULong ()
658 return new ULongConstant ((ulong) Value
);
661 public override LongConstant
ConvertToLong ()
663 return new LongConstant (Value
);
666 public override UIntConstant
ConvertToUInt ()
671 return new UIntConstant ((uint) Value
);
674 public override IntConstant
ConvertToInt ()
679 public override bool IsNegative
{
685 public override bool IsZeroInteger
{
686 get { return Value == 0; }
690 public class UIntConstant
: Constant
{
691 public readonly uint Value
;
693 public UIntConstant (uint v
)
695 type
= TypeManager
.uint32_type
;
696 eclass
= ExprClass
.Value
;
700 public override void Emit (EmitContext ec
)
702 IntLiteral
.EmitInt (ec
.ig
, unchecked ((int) Value
));
705 public override string AsString ()
707 return Value
.ToString ();
710 public override object GetValue ()
715 public override DoubleConstant
ConvertToDouble ()
717 return new DoubleConstant (Value
);
720 public override FloatConstant
ConvertToFloat ()
722 return new FloatConstant (Value
);
725 public override ULongConstant
ConvertToULong ()
727 return new ULongConstant (Value
);
730 public override LongConstant
ConvertToLong ()
732 return new LongConstant (Value
);
735 public override UIntConstant
ConvertToUInt ()
740 public override IntConstant
ConvertToInt ()
745 public override bool IsNegative
{
751 public override bool IsZeroInteger
{
752 get { return Value == 0; }
756 public class LongConstant
: Constant
{
757 public readonly long Value
;
759 public LongConstant (long v
)
761 type
= TypeManager
.int64_type
;
762 eclass
= ExprClass
.Value
;
766 public override void Emit (EmitContext ec
)
768 ILGenerator ig
= ec
.ig
;
770 EmitLong (ig
, Value
);
773 static public void EmitLong (ILGenerator ig
, long l
)
776 IntLiteral
.EmitInt (ig
, unchecked ((int) l
));
777 ig
.Emit (OpCodes
.Conv_U8
);
779 ig
.Emit (OpCodes
.Ldc_I8
, l
);
783 public override string AsString ()
785 return Value
.ToString ();
788 public override object GetValue ()
793 public override DoubleConstant
ConvertToDouble ()
795 return new DoubleConstant (Value
);
798 public override FloatConstant
ConvertToFloat ()
800 return new FloatConstant (Value
);
803 public override ULongConstant
ConvertToULong ()
808 return new ULongConstant ((ulong) Value
);
811 public override LongConstant
ConvertToLong ()
816 public override UIntConstant
ConvertToUInt ()
821 public override IntConstant
ConvertToInt ()
826 public override bool IsNegative
{
832 public override bool IsZeroInteger
{
833 get { return Value == 0; }
837 public class ULongConstant
: Constant
{
838 public readonly ulong Value
;
840 public ULongConstant (ulong v
)
842 type
= TypeManager
.uint64_type
;
843 eclass
= ExprClass
.Value
;
847 public override void Emit (EmitContext ec
)
849 ILGenerator ig
= ec
.ig
;
851 LongLiteral
.EmitLong (ig
, unchecked ((long) Value
));
854 public override string AsString ()
856 return Value
.ToString ();
859 public override object GetValue ()
864 public override DoubleConstant
ConvertToDouble ()
866 return new DoubleConstant (Value
);
869 public override FloatConstant
ConvertToFloat ()
871 return new FloatConstant (Value
);
874 public override ULongConstant
ConvertToULong ()
879 public override LongConstant
ConvertToLong ()
884 public override UIntConstant
ConvertToUInt ()
889 public override IntConstant
ConvertToInt ()
894 public override bool IsNegative
{
900 public override bool IsZeroInteger
{
901 get { return Value == 0; }
905 public class FloatConstant
: Constant
{
906 public readonly float Value
;
908 public FloatConstant (float v
)
910 type
= TypeManager
.float_type
;
911 eclass
= ExprClass
.Value
;
915 public override void Emit (EmitContext ec
)
917 ec
.ig
.Emit (OpCodes
.Ldc_R4
, Value
);
920 public override string AsString ()
922 return Value
.ToString ();
925 public override object GetValue ()
930 public override DoubleConstant
ConvertToDouble ()
932 return new DoubleConstant (Value
);
935 public override FloatConstant
ConvertToFloat ()
940 public override LongConstant
ConvertToLong ()
945 public override UIntConstant
ConvertToUInt ()
950 public override IntConstant
ConvertToInt ()
955 public override bool IsNegative
{
962 public class DoubleConstant
: Constant
{
963 public readonly double Value
;
965 public DoubleConstant (double v
)
967 type
= TypeManager
.double_type
;
968 eclass
= ExprClass
.Value
;
972 public override void Emit (EmitContext ec
)
974 ec
.ig
.Emit (OpCodes
.Ldc_R8
, Value
);
977 public override string AsString ()
979 return Value
.ToString ();
982 public override object GetValue ()
987 public override DoubleConstant
ConvertToDouble ()
992 public override FloatConstant
ConvertToFloat ()
997 public override ULongConstant
ConvertToULong ()
1002 public override LongConstant
ConvertToLong ()
1007 public override UIntConstant
ConvertToUInt ()
1012 public override IntConstant
ConvertToInt ()
1017 public override bool IsNegative
{
1024 public class DecimalConstant
: Constant
{
1025 public readonly decimal Value
;
1027 public DecimalConstant (decimal d
)
1029 type
= TypeManager
.decimal_type
;
1030 eclass
= ExprClass
.Value
;
1034 override public string AsString ()
1036 return Value
.ToString ();
1039 public override object GetValue ()
1041 return (object) Value
;
1044 public override void Emit (EmitContext ec
)
1046 int [] words
= Decimal
.GetBits (Value
);
1049 // FIXME: we could optimize this, and call a better
1053 ILGenerator ig
= ec
.ig
;
1055 IntConstant
.EmitInt (ig
, words
[0]);
1056 IntConstant
.EmitInt (ig
, words
[1]);
1057 IntConstant
.EmitInt (ig
, words
[2]);
1060 IntConstant
.EmitInt (ig
, words
[3] >> 31);
1063 IntConstant
.EmitInt (ig
, (words
[3] >> 16) & 0xff);
1065 ig
.Emit (OpCodes
.Newobj
, TypeManager
.void_decimal_ctor_five_args
);
1068 public override bool IsNegative
{
1075 public class StringConstant
: Constant
{
1076 public readonly string Value
;
1078 public StringConstant (string s
)
1080 type
= TypeManager
.string_type
;
1081 eclass
= ExprClass
.Value
;
1085 // FIXME: Escape the string.
1086 override public string AsString ()
1088 return "\"" + Value
+ "\"";
1091 public override object GetValue ()
1096 public override void Emit (EmitContext ec
)
1099 ec
.ig
.Emit (OpCodes
.Ldnull
);
1101 ec
.ig
.Emit (OpCodes
.Ldstr
, Value
);
1104 public override bool IsNegative
{