**** Merged from MCS ****
[mono-project.git] / mcs / mcs / constant.cs
blob103572b1d54af86099bd3919309430dbb5359702
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
11 namespace Mono.CSharp {
13 using System;
14 using System.Reflection.Emit;
16 /// <summary>
17 /// Base class for constants and literals.
18 /// </summary>
19 public abstract class Constant : Expression {
20 /// <remarks>
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.
27 /// </remarks>
28 public abstract string AsString ();
30 override public string ToString ()
32 return this.GetType ().Name + " (" + AsString () + ")";
35 /// <summary>
36 /// This is used to obtain the actual value of the literal
37 /// cast into an object.
38 /// </summary>
39 public abstract object GetValue ();
41 /// <summary>
42 /// Constants are always born in a fully resolved state
43 /// </summary>
44 public override Expression DoResolve (EmitContext ec)
46 return this;
50 // The various ToXXXX conversion functions are used by the constant
51 // folding evaluator. A null value is returned if the conversion is
52 // not possible.
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 ();
64 if (c == null)
65 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
67 return c;
70 public FloatConstant ToFloat (Location loc)
72 FloatConstant c = ConvertToFloat ();
74 if (c == null)
75 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
77 return c;
80 public ULongConstant ToULong (Location loc)
82 ULongConstant c = ConvertToULong ();
84 if (c == null)
85 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
87 return c;
90 public LongConstant ToLong (Location loc)
92 LongConstant c = ConvertToLong ();
94 if (c == null)
95 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
97 return c;
100 public UIntConstant ToUInt (Location loc)
102 UIntConstant c = ConvertToUInt ();
104 if (c == null)
105 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
107 return c;
110 public IntConstant ToInt (Location loc)
112 IntConstant c = ConvertToInt ();
114 if (c == null)
115 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
117 return c;
120 public virtual DoubleConstant ConvertToDouble ()
122 return null;
125 public virtual FloatConstant ConvertToFloat ()
127 return null;
130 public virtual ULongConstant ConvertToULong ()
132 return null;
135 public virtual LongConstant ConvertToLong ()
137 return null;
140 public virtual UIntConstant ConvertToUInt ()
142 return null;
145 public virtual IntConstant ConvertToInt ()
147 return null;
150 public abstract bool IsNegative {
151 get;
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;
171 Value = val;
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)
187 if (Value)
188 ec.ig.Emit (OpCodes.Ldc_I4_1);
189 else
190 ec.ig.Emit (OpCodes.Ldc_I4_0);
193 public override bool IsNegative {
194 get {
195 return false;
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;
211 Value = v;
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 ()
226 return Value;
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 {
260 get {
261 return false;
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;
277 Value = v;
280 public override void Emit (EmitContext ec)
282 IntLiteral.EmitInt (ec.ig, Value);
285 static public string descape (char c)
287 switch (c){
288 case '\a':
289 return "\\a";
290 case '\b':
291 return "\\b";
292 case '\n':
293 return "\\n";
294 case '\t':
295 return "\\t";
296 case '\v':
297 return "\\v";
298 case '\r':
299 return "\\r";
300 case '\\':
301 return "\\\\";
302 case '\f':
303 return "\\f";
304 case '\0':
305 return "\\0";
306 case '"':
307 return "\\\"";
308 case '\'':
309 return "\\\'";
311 return c.ToString ();
314 public override string AsString ()
316 return "\"" + descape (Value) + "\"";
319 public override object GetValue ()
321 return Value;
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 {
355 get {
356 return false;
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;
372 Value = v;
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 ()
387 return Value;
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 ()
402 if (Value >= 0)
403 return new ULongConstant ((ulong) Value);
405 return null;
408 public override LongConstant ConvertToLong ()
410 return new LongConstant (Value);
413 public override UIntConstant ConvertToUInt ()
415 return null;
418 public override IntConstant ConvertToInt ()
420 return new IntConstant (Value);
423 public override bool IsNegative {
424 get {
425 return Value < 0;
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;
441 Value = v;
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 ()
456 return Value;
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 ()
471 return null;
474 public override LongConstant ConvertToLong ()
476 return new LongConstant (Value);
479 public override UIntConstant ConvertToUInt ()
481 return null;
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 {
494 get {
495 return Value < 0;
500 public class UShortConstant : Constant {
501 public readonly ushort Value;
503 public UShortConstant (ushort v)
505 type = TypeManager.ushort_type;
506 eclass = ExprClass.Value;
507 Value = v;
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 ()
522 return Value;
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 {
556 get {
557 return false;
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;
573 Value = v;
576 static public void EmitInt (ILGenerator ig, int i)
578 switch (i){
579 case -1:
580 ig.Emit (OpCodes.Ldc_I4_M1);
581 break;
583 case 0:
584 ig.Emit (OpCodes.Ldc_I4_0);
585 break;
587 case 1:
588 ig.Emit (OpCodes.Ldc_I4_1);
589 break;
591 case 2:
592 ig.Emit (OpCodes.Ldc_I4_2);
593 break;
595 case 3:
596 ig.Emit (OpCodes.Ldc_I4_3);
597 break;
599 case 4:
600 ig.Emit (OpCodes.Ldc_I4_4);
601 break;
603 case 5:
604 ig.Emit (OpCodes.Ldc_I4_5);
605 break;
607 case 6:
608 ig.Emit (OpCodes.Ldc_I4_6);
609 break;
611 case 7:
612 ig.Emit (OpCodes.Ldc_I4_7);
613 break;
615 case 8:
616 ig.Emit (OpCodes.Ldc_I4_8);
617 break;
619 default:
620 if (i >= -128 && i <= 127){
621 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
622 } else
623 ig.Emit (OpCodes.Ldc_I4, i);
624 break;
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 ()
640 return Value;
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 ()
655 if (Value < 0)
656 return null;
658 return new ULongConstant ((ulong) Value);
661 public override LongConstant ConvertToLong ()
663 return new LongConstant (Value);
666 public override UIntConstant ConvertToUInt ()
668 if (Value < 0)
669 return null;
671 return new UIntConstant ((uint) Value);
674 public override IntConstant ConvertToInt ()
676 return this;
679 public override bool IsNegative {
680 get {
681 return Value < 0;
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;
697 Value = v;
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 ()
712 return Value;
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 ()
737 return this;
740 public override IntConstant ConvertToInt ()
742 return null;
745 public override bool IsNegative {
746 get {
747 return false;
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;
763 Value = v;
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)
775 if ((l >> 32) == 0){
776 IntLiteral.EmitInt (ig, unchecked ((int) l));
777 ig.Emit (OpCodes.Conv_U8);
778 } else {
779 ig.Emit (OpCodes.Ldc_I8, l);
783 public override string AsString ()
785 return Value.ToString ();
788 public override object GetValue ()
790 return Value;
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 ()
805 if (Value < 0)
806 return null;
808 return new ULongConstant ((ulong) Value);
811 public override LongConstant ConvertToLong ()
813 return this;
816 public override UIntConstant ConvertToUInt ()
818 return null;
821 public override IntConstant ConvertToInt ()
823 return null;
826 public override bool IsNegative {
827 get {
828 return Value < 0;
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;
844 Value = v;
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 ()
861 return Value;
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 ()
876 return this;
879 public override LongConstant ConvertToLong ()
881 return null;
884 public override UIntConstant ConvertToUInt ()
886 return null;
889 public override IntConstant ConvertToInt ()
891 return null;
894 public override bool IsNegative {
895 get {
896 return false;
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;
912 Value = v;
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 ()
927 return Value;
930 public override DoubleConstant ConvertToDouble ()
932 return new DoubleConstant (Value);
935 public override FloatConstant ConvertToFloat ()
937 return this;
940 public override LongConstant ConvertToLong ()
942 return null;
945 public override UIntConstant ConvertToUInt ()
947 return null;
950 public override IntConstant ConvertToInt ()
952 return null;
955 public override bool IsNegative {
956 get {
957 return Value < 0;
962 public class DoubleConstant : Constant {
963 public readonly double Value;
965 public DoubleConstant (double v)
967 type = TypeManager.double_type;
968 eclass = ExprClass.Value;
969 Value = v;
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 ()
984 return Value;
987 public override DoubleConstant ConvertToDouble ()
989 return this;
992 public override FloatConstant ConvertToFloat ()
994 return null;
997 public override ULongConstant ConvertToULong ()
999 return null;
1002 public override LongConstant ConvertToLong ()
1004 return null;
1007 public override UIntConstant ConvertToUInt ()
1009 return null;
1012 public override IntConstant ConvertToInt ()
1014 return null;
1017 public override bool IsNegative {
1018 get {
1019 return Value < 0;
1024 public class DecimalConstant : Constant {
1025 public readonly decimal Value;
1027 public DecimalConstant (decimal d)
1029 type = TypeManager.decimal_type;
1030 eclass = ExprClass.Value;
1031 Value = d;
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
1050 // constructor
1053 ILGenerator ig = ec.ig;
1055 IntConstant.EmitInt (ig, words [0]);
1056 IntConstant.EmitInt (ig, words [1]);
1057 IntConstant.EmitInt (ig, words [2]);
1059 // sign
1060 IntConstant.EmitInt (ig, words [3] >> 31);
1062 // power
1063 IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
1065 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1068 public override bool IsNegative {
1069 get {
1070 return Value < 0;
1075 public class StringConstant : Constant {
1076 public readonly string Value;
1078 public StringConstant (string s)
1080 type = TypeManager.string_type;
1081 eclass = ExprClass.Value;
1082 Value = s;
1085 // FIXME: Escape the string.
1086 override public string AsString ()
1088 return "\"" + Value + "\"";
1091 public override object GetValue ()
1093 return Value;
1096 public override void Emit (EmitContext ec)
1098 if (Value == null)
1099 ec.ig.Emit (OpCodes.Ldnull);
1100 else
1101 ec.ig.Emit (OpCodes.Ldstr, Value);
1104 public override bool IsNegative {
1105 get {
1106 return false;