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 public class BoolConstant : Constant {
152 public readonly bool Value;
154 public BoolConstant (bool val)
156 type = TypeManager.bool_type;
157 eclass = ExprClass.Value;
162 override public string AsString ()
164 return Value ? "true" : "false";
167 public override object GetValue ()
169 return (object) Value;
173 public override void Emit (EmitContext ec)
176 ec.ig.Emit (OpCodes.Ldc_I4_1);
178 ec.ig.Emit (OpCodes.Ldc_I4_0);
182 public class ByteConstant : Constant {
183 public readonly byte Value;
185 public ByteConstant (byte v)
187 type = TypeManager.byte_type;
188 eclass = ExprClass.Value;
192 public override void Emit (EmitContext ec)
194 IntLiteral.EmitInt (ec.ig, Value);
197 public override string AsString ()
199 return Value.ToString ();
202 public override object GetValue ()
207 public override DoubleConstant ConvertToDouble ()
209 return new DoubleConstant (Value);
212 public override FloatConstant ConvertToFloat ()
214 return new FloatConstant (Value);
217 public override ULongConstant ConvertToULong ()
219 return new ULongConstant (Value);
222 public override LongConstant ConvertToLong ()
224 return new LongConstant (Value);
227 public override UIntConstant ConvertToUInt ()
229 return new UIntConstant (Value);
232 public override IntConstant ConvertToInt ()
234 return new IntConstant (Value);
238 public class CharConstant : Constant {
239 public readonly char Value;
241 public CharConstant (char v)
243 type = TypeManager.char_type;
244 eclass = ExprClass.Value;
248 public override void Emit (EmitContext ec)
250 IntLiteral.EmitInt (ec.ig, Value);
253 static public string descape (char c)
279 return c.ToString ();
282 public override string AsString ()
284 return "\"" + descape (Value) + "\"";
287 public override object GetValue ()
292 public override DoubleConstant ConvertToDouble ()
294 return new DoubleConstant (Value);
297 public override FloatConstant ConvertToFloat ()
299 return new FloatConstant (Value);
302 public override ULongConstant ConvertToULong ()
304 return new ULongConstant (Value);
307 public override LongConstant ConvertToLong ()
309 return new LongConstant (Value);
312 public override UIntConstant ConvertToUInt ()
314 return new UIntConstant (Value);
317 public override IntConstant ConvertToInt ()
319 return new IntConstant (Value);
323 public class SByteConstant : Constant {
324 public readonly sbyte Value;
326 public SByteConstant (sbyte v)
328 type = TypeManager.sbyte_type;
329 eclass = ExprClass.Value;
333 public override void Emit (EmitContext ec)
335 IntLiteral.EmitInt (ec.ig, Value);
338 public override string AsString ()
340 return Value.ToString ();
343 public override object GetValue ()
348 public override DoubleConstant ConvertToDouble ()
350 return new DoubleConstant (Value);
353 public override FloatConstant ConvertToFloat ()
355 return new FloatConstant (Value);
358 public override ULongConstant ConvertToULong ()
361 return new ULongConstant ((ulong) Value);
366 public override LongConstant ConvertToLong ()
368 return new LongConstant (Value);
371 public override UIntConstant ConvertToUInt ()
376 public override IntConstant ConvertToInt ()
378 return new IntConstant (Value);
382 public class ShortConstant : Constant {
383 public readonly short Value;
385 public ShortConstant (short v)
387 type = TypeManager.short_type;
388 eclass = ExprClass.Value;
392 public override void Emit (EmitContext ec)
394 IntLiteral.EmitInt (ec.ig, Value);
397 public override string AsString ()
399 return Value.ToString ();
402 public override object GetValue ()
407 public override DoubleConstant ConvertToDouble ()
409 return new DoubleConstant (Value);
412 public override FloatConstant ConvertToFloat ()
414 return new FloatConstant (Value);
417 public override ULongConstant ConvertToULong ()
422 public override LongConstant ConvertToLong ()
424 return new LongConstant (Value);
427 public override UIntConstant ConvertToUInt ()
432 public override IntConstant ConvertToInt ()
434 return new IntConstant (Value);
438 public class UShortConstant : Constant {
439 public readonly ushort Value;
441 public UShortConstant (ushort v)
443 type = TypeManager.ushort_type;
444 eclass = ExprClass.Value;
448 public override void Emit (EmitContext ec)
450 IntLiteral.EmitInt (ec.ig, Value);
453 public override string AsString ()
455 return Value.ToString ();
458 public override object GetValue ()
463 public override DoubleConstant ConvertToDouble ()
465 return new DoubleConstant (Value);
468 public override FloatConstant ConvertToFloat ()
470 return new FloatConstant (Value);
473 public override ULongConstant ConvertToULong ()
475 return new ULongConstant (Value);
478 public override LongConstant ConvertToLong ()
480 return new LongConstant (Value);
483 public override UIntConstant ConvertToUInt ()
485 return new UIntConstant (Value);
488 public override IntConstant ConvertToInt ()
490 return new IntConstant (Value);
494 public class IntConstant : Constant {
495 public readonly int Value;
497 public IntConstant (int v)
499 type = TypeManager.int32_type;
500 eclass = ExprClass.Value;
504 static public void EmitInt (ILGenerator ig, int i)
508 ig.Emit (OpCodes.Ldc_I4_M1);
512 ig.Emit (OpCodes.Ldc_I4_0);
516 ig.Emit (OpCodes.Ldc_I4_1);
520 ig.Emit (OpCodes.Ldc_I4_2);
524 ig.Emit (OpCodes.Ldc_I4_3);
528 ig.Emit (OpCodes.Ldc_I4_4);
532 ig.Emit (OpCodes.Ldc_I4_5);
536 ig.Emit (OpCodes.Ldc_I4_6);
540 ig.Emit (OpCodes.Ldc_I4_7);
544 ig.Emit (OpCodes.Ldc_I4_8);
548 if (i >= -128 && i <= 127){
549 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
551 ig.Emit (OpCodes.Ldc_I4, i);
556 public override void Emit (EmitContext ec)
558 EmitInt (ec.ig, Value);
561 public override string AsString ()
563 return Value.ToString ();
566 public override object GetValue ()
571 public override DoubleConstant ConvertToDouble ()
573 return new DoubleConstant (Value);
576 public override FloatConstant ConvertToFloat ()
578 return new FloatConstant (Value);
581 public override ULongConstant ConvertToULong ()
586 return new ULongConstant ((ulong) Value);
589 public override LongConstant ConvertToLong ()
591 return new LongConstant (Value);
594 public override UIntConstant ConvertToUInt ()
599 return new UIntConstant ((uint) Value);
602 public override IntConstant ConvertToInt ()
608 public class UIntConstant : Constant {
609 public readonly uint Value;
611 public UIntConstant (uint v)
613 type = TypeManager.uint32_type;
614 eclass = ExprClass.Value;
618 public override void Emit (EmitContext ec)
620 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
623 public override string AsString ()
625 return Value.ToString ();
628 public override object GetValue ()
633 public override DoubleConstant ConvertToDouble ()
635 return new DoubleConstant (Value);
638 public override FloatConstant ConvertToFloat ()
640 return new FloatConstant (Value);
643 public override ULongConstant ConvertToULong ()
645 return new ULongConstant (Value);
648 public override LongConstant ConvertToLong ()
650 return new LongConstant (Value);
653 public override UIntConstant ConvertToUInt ()
658 public override IntConstant ConvertToInt ()
664 public class LongConstant : Constant {
665 public readonly long Value;
667 public LongConstant (long v)
669 type = TypeManager.int64_type;
670 eclass = ExprClass.Value;
674 public override void Emit (EmitContext ec)
676 ILGenerator ig = ec.ig;
678 EmitLong (ig, Value);
681 static public void EmitLong (ILGenerator ig, long l)
684 IntLiteral.EmitInt (ig, unchecked ((int) l));
685 ig.Emit (OpCodes.Conv_U8);
687 ig.Emit (OpCodes.Ldc_I8, l);
691 public override string AsString ()
693 return Value.ToString ();
696 public override object GetValue ()
701 public override DoubleConstant ConvertToDouble ()
703 return new DoubleConstant (Value);
706 public override FloatConstant ConvertToFloat ()
708 return new FloatConstant (Value);
711 public override ULongConstant ConvertToULong ()
716 return new ULongConstant ((ulong) Value);
719 public override LongConstant ConvertToLong ()
724 public override UIntConstant ConvertToUInt ()
729 public override IntConstant ConvertToInt ()
735 public class ULongConstant : Constant {
736 public readonly ulong Value;
738 public ULongConstant (ulong v)
740 type = TypeManager.uint64_type;
741 eclass = ExprClass.Value;
745 public override void Emit (EmitContext ec)
747 ILGenerator ig = ec.ig;
749 LongLiteral.EmitLong (ig, unchecked ((long) Value));
752 public override string AsString ()
754 return Value.ToString ();
757 public override object GetValue ()
762 public override DoubleConstant ConvertToDouble ()
764 return new DoubleConstant (Value);
767 public override FloatConstant ConvertToFloat ()
769 return new FloatConstant (Value);
772 public override ULongConstant ConvertToULong ()
777 public override LongConstant ConvertToLong ()
782 public override UIntConstant ConvertToUInt ()
787 public override IntConstant ConvertToInt ()
793 public class FloatConstant : Constant {
794 public readonly float Value;
796 public FloatConstant (float v)
798 type = TypeManager.float_type;
799 eclass = ExprClass.Value;
803 public override void Emit (EmitContext ec)
805 ec.ig.Emit (OpCodes.Ldc_R4, Value);
808 public override string AsString ()
810 return Value.ToString ();
813 public override object GetValue ()
818 public override DoubleConstant ConvertToDouble ()
820 return new DoubleConstant (Value);
823 public override FloatConstant ConvertToFloat ()
828 public override LongConstant ConvertToLong ()
833 public override UIntConstant ConvertToUInt ()
838 public override IntConstant ConvertToInt ()
844 public class DoubleConstant : Constant {
845 public readonly double Value;
847 public DoubleConstant (double v)
849 type = TypeManager.double_type;
850 eclass = ExprClass.Value;
854 public override void Emit (EmitContext ec)
856 ec.ig.Emit (OpCodes.Ldc_R8, Value);
859 public override string AsString ()
861 return Value.ToString ();
864 public override object GetValue ()
869 public override DoubleConstant ConvertToDouble ()
874 public override FloatConstant ConvertToFloat ()
879 public override ULongConstant ConvertToULong ()
884 public override LongConstant ConvertToLong ()
889 public override UIntConstant ConvertToUInt ()
894 public override IntConstant ConvertToInt ()
900 public class DecimalConstant : Constant {
901 public readonly decimal Value;
903 public DecimalConstant (decimal d)
905 type = TypeManager.decimal_type;
906 eclass = ExprClass.Value;
910 override public string AsString ()
912 return Value.ToString ();
915 public override object GetValue ()
917 return (object) Value;
920 public override void Emit (EmitContext ec)
922 int [] words = Decimal.GetBits (Value);
925 // FIXME: we could optimize this, and call a better
929 ILGenerator ig = ec.ig;
931 IntConstant.EmitInt (ig, words [0]);
932 IntConstant.EmitInt (ig, words [1]);
933 IntConstant.EmitInt (ig, words [2]);
936 IntConstant.EmitInt (ig, words [3] >> 31);
939 IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
941 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
945 public class StringConstant : Constant {
946 public readonly string Value;
948 public StringConstant (string s)
950 type = TypeManager.string_type;
951 eclass = ExprClass.Value;
955 // FIXME: Escape the string.
956 override public string AsString ()
958 return "\"" + Value + "\"";
961 public override object GetValue ()
966 public override void Emit (EmitContext ec)
968 ec.ig.Emit (OpCodes.Ldstr, Value);