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 ()
151 // Returns true iff 1) the stack type of this is one of Object,
152 // int32, int64 and 2) this == 0 or this == null.
154 public virtual bool IsZeroInteger {
155 get { return false; }
159 public class BoolConstant : Constant {
160 public readonly bool Value;
162 public BoolConstant (bool val)
164 type = TypeManager.bool_type;
165 eclass = ExprClass.Value;
170 override public string AsString ()
172 return Value ? "true" : "false";
175 public override object GetValue ()
177 return (object) Value;
181 public override void Emit (EmitContext ec)
184 ec.ig.Emit (OpCodes.Ldc_I4_1);
186 ec.ig.Emit (OpCodes.Ldc_I4_0);
189 public override bool IsZeroInteger {
190 get { return Value == false; }
194 public class ByteConstant : Constant {
195 public readonly byte Value;
197 public ByteConstant (byte v)
199 type = TypeManager.byte_type;
200 eclass = ExprClass.Value;
204 public override void Emit (EmitContext ec)
206 IntLiteral.EmitInt (ec.ig, Value);
209 public override string AsString ()
211 return Value.ToString ();
214 public override object GetValue ()
219 public override DoubleConstant ConvertToDouble ()
221 return new DoubleConstant (Value);
224 public override FloatConstant ConvertToFloat ()
226 return new FloatConstant (Value);
229 public override ULongConstant ConvertToULong ()
231 return new ULongConstant (Value);
234 public override LongConstant ConvertToLong ()
236 return new LongConstant (Value);
239 public override UIntConstant ConvertToUInt ()
241 return new UIntConstant (Value);
244 public override IntConstant ConvertToInt ()
246 return new IntConstant (Value);
249 public override bool IsZeroInteger {
250 get { return Value == 0; }
254 public class CharConstant : Constant {
255 public readonly char Value;
257 public CharConstant (char v)
259 type = TypeManager.char_type;
260 eclass = ExprClass.Value;
264 public override void Emit (EmitContext ec)
266 IntLiteral.EmitInt (ec.ig, Value);
269 static public string descape (char c)
295 return c.ToString ();
298 public override string AsString ()
300 return "\"" + descape (Value) + "\"";
303 public override object GetValue ()
308 public override DoubleConstant ConvertToDouble ()
310 return new DoubleConstant (Value);
313 public override FloatConstant ConvertToFloat ()
315 return new FloatConstant (Value);
318 public override ULongConstant ConvertToULong ()
320 return new ULongConstant (Value);
323 public override LongConstant ConvertToLong ()
325 return new LongConstant (Value);
328 public override UIntConstant ConvertToUInt ()
330 return new UIntConstant (Value);
333 public override IntConstant ConvertToInt ()
335 return new IntConstant (Value);
338 public override bool IsZeroInteger {
339 get { return Value == '\0'; }
343 public class SByteConstant : Constant {
344 public readonly sbyte Value;
346 public SByteConstant (sbyte v)
348 type = TypeManager.sbyte_type;
349 eclass = ExprClass.Value;
353 public override void Emit (EmitContext ec)
355 IntLiteral.EmitInt (ec.ig, Value);
358 public override string AsString ()
360 return Value.ToString ();
363 public override object GetValue ()
368 public override DoubleConstant ConvertToDouble ()
370 return new DoubleConstant (Value);
373 public override FloatConstant ConvertToFloat ()
375 return new FloatConstant (Value);
378 public override ULongConstant ConvertToULong ()
381 return new ULongConstant ((ulong) Value);
386 public override LongConstant ConvertToLong ()
388 return new LongConstant (Value);
391 public override UIntConstant ConvertToUInt ()
396 public override IntConstant ConvertToInt ()
398 return new IntConstant (Value);
401 public override bool IsZeroInteger {
402 get { return Value == 0; }
406 public class ShortConstant : Constant {
407 public readonly short Value;
409 public ShortConstant (short v)
411 type = TypeManager.short_type;
412 eclass = ExprClass.Value;
416 public override void Emit (EmitContext ec)
418 IntLiteral.EmitInt (ec.ig, Value);
421 public override string AsString ()
423 return Value.ToString ();
426 public override object GetValue ()
431 public override DoubleConstant ConvertToDouble ()
433 return new DoubleConstant (Value);
436 public override FloatConstant ConvertToFloat ()
438 return new FloatConstant (Value);
441 public override ULongConstant ConvertToULong ()
446 public override LongConstant ConvertToLong ()
448 return new LongConstant (Value);
451 public override UIntConstant ConvertToUInt ()
456 public override IntConstant ConvertToInt ()
458 return new IntConstant (Value);
461 public override bool IsZeroInteger {
462 get { return Value == 0; }
466 public class UShortConstant : Constant {
467 public readonly ushort Value;
469 public UShortConstant (ushort v)
471 type = TypeManager.ushort_type;
472 eclass = ExprClass.Value;
476 public override void Emit (EmitContext ec)
478 IntLiteral.EmitInt (ec.ig, Value);
481 public override string AsString ()
483 return Value.ToString ();
486 public override object GetValue ()
491 public override DoubleConstant ConvertToDouble ()
493 return new DoubleConstant (Value);
496 public override FloatConstant ConvertToFloat ()
498 return new FloatConstant (Value);
501 public override ULongConstant ConvertToULong ()
503 return new ULongConstant (Value);
506 public override LongConstant ConvertToLong ()
508 return new LongConstant (Value);
511 public override UIntConstant ConvertToUInt ()
513 return new UIntConstant (Value);
516 public override IntConstant ConvertToInt ()
518 return new IntConstant (Value);
521 public override bool IsZeroInteger {
522 get { return Value == 0; }
526 public class IntConstant : Constant {
527 public readonly int Value;
529 public IntConstant (int v)
531 type = TypeManager.int32_type;
532 eclass = ExprClass.Value;
536 static public void EmitInt (ILGenerator ig, int i)
540 ig.Emit (OpCodes.Ldc_I4_M1);
544 ig.Emit (OpCodes.Ldc_I4_0);
548 ig.Emit (OpCodes.Ldc_I4_1);
552 ig.Emit (OpCodes.Ldc_I4_2);
556 ig.Emit (OpCodes.Ldc_I4_3);
560 ig.Emit (OpCodes.Ldc_I4_4);
564 ig.Emit (OpCodes.Ldc_I4_5);
568 ig.Emit (OpCodes.Ldc_I4_6);
572 ig.Emit (OpCodes.Ldc_I4_7);
576 ig.Emit (OpCodes.Ldc_I4_8);
580 if (i >= -128 && i <= 127){
581 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
583 ig.Emit (OpCodes.Ldc_I4, i);
588 public override void Emit (EmitContext ec)
590 EmitInt (ec.ig, Value);
593 public override string AsString ()
595 return Value.ToString ();
598 public override object GetValue ()
603 public override DoubleConstant ConvertToDouble ()
605 return new DoubleConstant (Value);
608 public override FloatConstant ConvertToFloat ()
610 return new FloatConstant (Value);
613 public override ULongConstant ConvertToULong ()
618 return new ULongConstant ((ulong) Value);
621 public override LongConstant ConvertToLong ()
623 return new LongConstant (Value);
626 public override UIntConstant ConvertToUInt ()
631 return new UIntConstant ((uint) Value);
634 public override IntConstant ConvertToInt ()
639 public override bool IsZeroInteger {
640 get { return Value == 0; }
644 public class UIntConstant : Constant {
645 public readonly uint Value;
647 public UIntConstant (uint v)
649 type = TypeManager.uint32_type;
650 eclass = ExprClass.Value;
654 public override void Emit (EmitContext ec)
656 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
659 public override string AsString ()
661 return Value.ToString ();
664 public override object GetValue ()
669 public override DoubleConstant ConvertToDouble ()
671 return new DoubleConstant (Value);
674 public override FloatConstant ConvertToFloat ()
676 return new FloatConstant (Value);
679 public override ULongConstant ConvertToULong ()
681 return new ULongConstant (Value);
684 public override LongConstant ConvertToLong ()
686 return new LongConstant (Value);
689 public override UIntConstant ConvertToUInt ()
694 public override IntConstant ConvertToInt ()
699 public override bool IsZeroInteger {
700 get { return Value == 0; }
704 public class LongConstant : Constant {
705 public readonly long Value;
707 public LongConstant (long v)
709 type = TypeManager.int64_type;
710 eclass = ExprClass.Value;
714 public override void Emit (EmitContext ec)
716 ILGenerator ig = ec.ig;
718 EmitLong (ig, Value);
721 static public void EmitLong (ILGenerator ig, long l)
724 IntLiteral.EmitInt (ig, unchecked ((int) l));
725 ig.Emit (OpCodes.Conv_U8);
727 ig.Emit (OpCodes.Ldc_I8, l);
731 public override string AsString ()
733 return Value.ToString ();
736 public override object GetValue ()
741 public override DoubleConstant ConvertToDouble ()
743 return new DoubleConstant (Value);
746 public override FloatConstant ConvertToFloat ()
748 return new FloatConstant (Value);
751 public override ULongConstant ConvertToULong ()
756 return new ULongConstant ((ulong) Value);
759 public override LongConstant ConvertToLong ()
764 public override UIntConstant ConvertToUInt ()
769 public override IntConstant ConvertToInt ()
774 public override bool IsZeroInteger {
775 get { return Value == 0; }
779 public class ULongConstant : Constant {
780 public readonly ulong Value;
782 public ULongConstant (ulong v)
784 type = TypeManager.uint64_type;
785 eclass = ExprClass.Value;
789 public override void Emit (EmitContext ec)
791 ILGenerator ig = ec.ig;
793 LongLiteral.EmitLong (ig, unchecked ((long) Value));
796 public override string AsString ()
798 return Value.ToString ();
801 public override object GetValue ()
806 public override DoubleConstant ConvertToDouble ()
808 return new DoubleConstant (Value);
811 public override FloatConstant ConvertToFloat ()
813 return new FloatConstant (Value);
816 public override ULongConstant ConvertToULong ()
821 public override LongConstant ConvertToLong ()
826 public override UIntConstant ConvertToUInt ()
831 public override IntConstant ConvertToInt ()
836 public override bool IsZeroInteger {
837 get { return Value == 0; }
841 public class FloatConstant : Constant {
842 public readonly float Value;
844 public FloatConstant (float v)
846 type = TypeManager.float_type;
847 eclass = ExprClass.Value;
851 public override void Emit (EmitContext ec)
853 ec.ig.Emit (OpCodes.Ldc_R4, Value);
856 public override string AsString ()
858 return Value.ToString ();
861 public override object GetValue ()
866 public override DoubleConstant ConvertToDouble ()
868 return new DoubleConstant (Value);
871 public override FloatConstant ConvertToFloat ()
876 public override LongConstant ConvertToLong ()
881 public override UIntConstant ConvertToUInt ()
886 public override IntConstant ConvertToInt ()
892 public class DoubleConstant : Constant {
893 public readonly double Value;
895 public DoubleConstant (double v)
897 type = TypeManager.double_type;
898 eclass = ExprClass.Value;
902 public override void Emit (EmitContext ec)
904 ec.ig.Emit (OpCodes.Ldc_R8, Value);
907 public override string AsString ()
909 return Value.ToString ();
912 public override object GetValue ()
917 public override DoubleConstant ConvertToDouble ()
922 public override FloatConstant ConvertToFloat ()
927 public override ULongConstant ConvertToULong ()
932 public override LongConstant ConvertToLong ()
937 public override UIntConstant ConvertToUInt ()
942 public override IntConstant ConvertToInt ()
948 public class DecimalConstant : Constant {
949 public readonly decimal Value;
951 public DecimalConstant (decimal d)
953 type = TypeManager.decimal_type;
954 eclass = ExprClass.Value;
958 override public string AsString ()
960 return Value.ToString ();
963 public override object GetValue ()
965 return (object) Value;
968 public override void Emit (EmitContext ec)
970 int [] words = Decimal.GetBits (Value);
973 // FIXME: we could optimize this, and call a better
977 ILGenerator ig = ec.ig;
979 IntConstant.EmitInt (ig, words [0]);
980 IntConstant.EmitInt (ig, words [1]);
981 IntConstant.EmitInt (ig, words [2]);
984 IntConstant.EmitInt (ig, words [3] >> 31);
987 IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
989 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
993 public class StringConstant : Constant {
994 public readonly string Value;
996 public StringConstant (string s)
998 type = TypeManager.string_type;
999 eclass = ExprClass.Value;
1003 // FIXME: Escape the string.
1004 override public string AsString ()
1006 return "\"" + Value + "\"";
1009 public override object GetValue ()
1014 public override void Emit (EmitContext ec)
1017 ec.ig.Emit (OpCodes.Ldnull);
1019 ec.ig.Emit (OpCodes.Ldstr, Value);