2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2001 Ximian, Inc.
12 namespace Mono.CSharp {
15 using System.Reflection.Emit;
16 using System.Collections;
19 /// Base class for constants and literals.
21 public abstract class Constant : Expression {
23 protected Constant (Location loc)
29 /// This is different from ToString in that ToString
30 /// is supposed to be there for debugging purposes,
31 /// and is not guaranteed to be useful for anything else,
32 /// AsString() will provide something that can be used
33 /// for round-tripping C# code. Maybe it can be used
34 /// for IL assembly as well.
36 public abstract string AsString ();
38 override public string ToString ()
40 return this.GetType ().Name + " (" + AsString () + ")";
43 public override bool GetAttributableValue (Type value_type, out object value)
45 if (value_type == TypeManager.object_type) {
46 value = GetTypedValue ();
50 Constant c = ImplicitConversionRequired (value_type, loc);
56 value = c.GetTypedValue ();
61 /// This is used to obtain the actual value of the literal
62 /// cast into an object.
64 public abstract object GetValue ();
66 public virtual object GetTypedValue ()
72 /// Constants are always born in a fully resolved state
74 public override Expression DoResolve (EmitContext ec)
79 public Constant ImplicitConversionRequired (Type type, Location loc)
81 Constant c = ConvertImplicitly (type);
83 Error_ValueCannotBeConverted (null, loc, type, false);
87 public virtual Constant ConvertImplicitly (Type type)
89 if (this.type == type)
92 if (Convert.ImplicitNumericConversion (this, type) == null)
96 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
99 // We should always catch the error before this is ever
100 // reached, by calling Convert.ImplicitStandardConversionExists
102 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
103 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
106 return CreateConstant (type, constant_value, loc);
109 /// Returns a constant instance based on Type
110 /// The returned value is already resolved.
111 public static Constant CreateConstant (Type t, object v, Location loc)
113 if (t == TypeManager.int32_type)
114 return new IntConstant ((int) v, loc);
115 if (t == TypeManager.string_type)
116 return new StringConstant ((string) v, loc);
117 if (t == TypeManager.uint32_type)
118 return new UIntConstant ((uint) v, loc);
119 if (t == TypeManager.int64_type)
120 return new LongConstant ((long) v, loc);
121 if (t == TypeManager.uint64_type)
122 return new ULongConstant ((ulong) v, loc);
123 if (t == TypeManager.float_type)
124 return new FloatConstant ((float) v, loc);
125 if (t == TypeManager.double_type)
126 return new DoubleConstant ((double) v, loc);
127 if (t == TypeManager.short_type)
128 return new ShortConstant ((short)v, loc);
129 if (t == TypeManager.ushort_type)
130 return new UShortConstant ((ushort)v, loc);
131 if (t == TypeManager.sbyte_type)
132 return new SByteConstant ((sbyte)v, loc);
133 if (t == TypeManager.byte_type)
134 return new ByteConstant ((byte)v, loc);
135 if (t == TypeManager.char_type)
136 return new CharConstant ((char)v, loc);
137 if (t == TypeManager.bool_type)
138 return new BoolConstant ((bool) v, loc);
139 if (t == TypeManager.decimal_type)
140 return new DecimalConstant ((decimal) v, loc);
141 if (TypeManager.IsEnumType (t)) {
142 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
144 real_type = System.Enum.GetUnderlyingType (real_type);
145 return new EnumConstant (CreateConstant (real_type, v, loc), t);
147 if (v == null && !TypeManager.IsValueType (t))
148 return new EmptyConstantCast (new NullConstant (loc), t);
150 throw new Exception ("Unknown type for constant (" + t +
154 public override Expression CreateExpressionTree (EmitContext ec)
156 ArrayList args = new ArrayList (2);
157 args.Add (new Argument (this));
158 args.Add (new Argument (
159 new TypeOf (new TypeExpression (type, Location), Location)));
161 return CreateExpressionFactoryCall ("Constant", args);
166 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
167 /// It throws OverflowException
169 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
170 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
173 /// Attempts to do a compile-time folding of a constant cast.
175 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
178 return TryReduce (ec, target_type);
180 catch (OverflowException) {
181 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
182 GetValue ().ToString (), TypeManager.CSharpName (target_type));
187 Constant TryReduce (EmitContext ec, Type target_type)
189 if (Type == target_type)
192 if (TypeManager.IsEnumType (target_type)) {
193 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
197 return new EnumConstant (c, target_type);
200 return ConvertExplicitly (ec.ConstantCheckState, target_type);
203 public abstract Constant Increment ();
206 /// Need to pass type as the constant can require a boxing
207 /// and in such case no optimization is possible
209 public bool IsDefaultInitializer (Type type)
212 return IsDefaultValue;
214 return Type == TypeManager.null_type;
217 public abstract bool IsDefaultValue {
221 public abstract bool IsNegative {
226 // Returns true iff 1) the stack type of this is one of Object,
227 // int32, int64 and 2) this == 0 or this == null.
229 public virtual bool IsZeroInteger {
230 get { return false; }
233 protected override void CloneTo (CloneContext clonectx, Expression target)
235 // CloneTo: Nothing, we do not keep any state on this expression
239 public abstract class IntegralConstant : Constant {
240 protected IntegralConstant (Location loc) :
245 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
248 ConvertExplicitly (true, target);
249 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
253 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
254 GetValue ().ToString (), TypeManager.CSharpName (target));
259 public class BoolConstant : Constant {
260 public readonly bool Value;
262 public BoolConstant (bool val, Location loc):
265 type = TypeManager.bool_type;
266 eclass = ExprClass.Value;
271 override public string AsString ()
273 return Value ? "true" : "false";
276 public override object GetValue ()
278 return (object) Value;
282 public override void Emit (EmitContext ec)
285 ec.ig.Emit (OpCodes.Ldc_I4_1);
287 ec.ig.Emit (OpCodes.Ldc_I4_0);
290 public override Constant Increment ()
292 throw new NotSupportedException ();
295 public override bool IsDefaultValue {
301 public override bool IsNegative {
307 public override bool IsZeroInteger {
308 get { return Value == false; }
311 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
318 public class ByteConstant : IntegralConstant {
319 public readonly byte Value;
321 public ByteConstant (byte v, Location loc):
324 type = TypeManager.byte_type;
325 eclass = ExprClass.Value;
329 public override void Emit (EmitContext ec)
331 IntLiteral.EmitInt (ec.ig, Value);
334 public override string AsString ()
336 return Value.ToString ();
339 public override object GetValue ()
344 public override Constant Increment ()
346 return new ByteConstant (checked ((byte)(Value + 1)), loc);
349 public override bool IsDefaultValue {
355 public override bool IsNegative {
361 public override bool IsZeroInteger {
362 get { return Value == 0; }
365 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
367 if (target_type == TypeManager.sbyte_type) {
368 if (in_checked_context){
369 if (Value > SByte.MaxValue)
370 throw new OverflowException ();
372 return new SByteConstant ((sbyte) Value, Location);
374 if (target_type == TypeManager.short_type)
375 return new ShortConstant ((short) Value, Location);
376 if (target_type == TypeManager.ushort_type)
377 return new UShortConstant ((ushort) Value, Location);
378 if (target_type == TypeManager.int32_type)
379 return new IntConstant ((int) Value, Location);
380 if (target_type == TypeManager.uint32_type)
381 return new UIntConstant ((uint) Value, Location);
382 if (target_type == TypeManager.int64_type)
383 return new LongConstant ((long) Value, Location);
384 if (target_type == TypeManager.uint64_type)
385 return new ULongConstant ((ulong) Value, Location);
386 if (target_type == TypeManager.float_type)
387 return new FloatConstant ((float) Value, Location);
388 if (target_type == TypeManager.double_type)
389 return new DoubleConstant ((double) Value, Location);
390 if (target_type == TypeManager.char_type)
391 return new CharConstant ((char) Value, Location);
392 if (target_type == TypeManager.decimal_type)
393 return new DecimalConstant ((decimal) Value, Location);
400 public class CharConstant : Constant {
401 public readonly char Value;
403 public CharConstant (char v, Location loc):
406 type = TypeManager.char_type;
407 eclass = ExprClass.Value;
411 public override void Emit (EmitContext ec)
413 IntLiteral.EmitInt (ec.ig, Value);
416 static public string descape (char c)
442 return c.ToString ();
445 public override string AsString ()
447 return "\"" + descape (Value) + "\"";
450 public override object GetValue ()
455 public override Constant Increment ()
457 return new CharConstant (checked ((char)(Value + 1)), loc);
460 public override bool IsDefaultValue {
466 public override bool IsNegative {
472 public override bool IsZeroInteger {
473 get { return Value == '\0'; }
476 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
478 if (target_type == TypeManager.byte_type) {
479 if (in_checked_context){
480 if (Value < Byte.MinValue || Value > Byte.MaxValue)
481 throw new OverflowException ();
483 return new ByteConstant ((byte) Value, Location);
485 if (target_type == TypeManager.sbyte_type) {
486 if (in_checked_context){
487 if (Value > SByte.MaxValue)
488 throw new OverflowException ();
490 return new SByteConstant ((sbyte) Value, Location);
492 if (target_type == TypeManager.short_type) {
493 if (in_checked_context){
494 if (Value > Int16.MaxValue)
495 throw new OverflowException ();
497 return new ShortConstant ((short) Value, Location);
499 if (target_type == TypeManager.int32_type)
500 return new IntConstant ((int) Value, Location);
501 if (target_type == TypeManager.uint32_type)
502 return new UIntConstant ((uint) Value, Location);
503 if (target_type == TypeManager.int64_type)
504 return new LongConstant ((long) Value, Location);
505 if (target_type == TypeManager.uint64_type)
506 return new ULongConstant ((ulong) Value, Location);
507 if (target_type == TypeManager.float_type)
508 return new FloatConstant ((float) Value, Location);
509 if (target_type == TypeManager.double_type)
510 return new DoubleConstant ((double) Value, Location);
511 if (target_type == TypeManager.decimal_type)
512 return new DecimalConstant ((decimal) Value, Location);
519 public class SByteConstant : IntegralConstant {
520 public readonly sbyte Value;
522 public SByteConstant (sbyte v, Location loc):
525 type = TypeManager.sbyte_type;
526 eclass = ExprClass.Value;
530 public override void Emit (EmitContext ec)
532 IntLiteral.EmitInt (ec.ig, Value);
535 public override string AsString ()
537 return Value.ToString ();
540 public override object GetValue ()
545 public override Constant Increment ()
547 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
550 public override bool IsDefaultValue {
556 public override bool IsNegative {
562 public override bool IsZeroInteger {
563 get { return Value == 0; }
566 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
568 if (target_type == TypeManager.byte_type) {
569 if (in_checked_context && Value < 0)
570 throw new OverflowException ();
571 return new ByteConstant ((byte) Value, Location);
573 if (target_type == TypeManager.short_type)
574 return new ShortConstant ((short) Value, Location);
575 if (target_type == TypeManager.ushort_type) {
576 if (in_checked_context && Value < 0)
577 throw new OverflowException ();
578 return new UShortConstant ((ushort) Value, Location);
579 } if (target_type == TypeManager.int32_type)
580 return new IntConstant ((int) Value, Location);
581 if (target_type == TypeManager.uint32_type) {
582 if (in_checked_context && Value < 0)
583 throw new OverflowException ();
584 return new UIntConstant ((uint) Value, Location);
585 } if (target_type == TypeManager.int64_type)
586 return new LongConstant ((long) Value, Location);
587 if (target_type == TypeManager.uint64_type) {
588 if (in_checked_context && Value < 0)
589 throw new OverflowException ();
590 return new ULongConstant ((ulong) Value, Location);
592 if (target_type == TypeManager.float_type)
593 return new FloatConstant ((float) Value, Location);
594 if (target_type == TypeManager.double_type)
595 return new DoubleConstant ((double) Value, Location);
596 if (target_type == TypeManager.char_type) {
597 if (in_checked_context && Value < 0)
598 throw new OverflowException ();
599 return new CharConstant ((char) Value, Location);
601 if (target_type == TypeManager.decimal_type)
602 return new DecimalConstant ((decimal) Value, Location);
609 public class ShortConstant : IntegralConstant {
610 public readonly short Value;
612 public ShortConstant (short v, Location loc):
615 type = TypeManager.short_type;
616 eclass = ExprClass.Value;
620 public override void Emit (EmitContext ec)
622 IntLiteral.EmitInt (ec.ig, Value);
625 public override string AsString ()
627 return Value.ToString ();
630 public override object GetValue ()
635 public override Constant Increment ()
637 return new ShortConstant (checked((short)(Value + 1)), loc);
640 public override bool IsDefaultValue {
646 public override bool IsZeroInteger {
647 get { return Value == 0; }
650 public override bool IsNegative {
656 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
658 if (target_type == TypeManager.byte_type) {
659 if (in_checked_context){
660 if (Value < Byte.MinValue || Value > Byte.MaxValue)
661 throw new OverflowException ();
663 return new ByteConstant ((byte) Value, Location);
665 if (target_type == TypeManager.sbyte_type) {
666 if (in_checked_context){
667 if (Value < SByte.MinValue || Value > SByte.MaxValue)
668 throw new OverflowException ();
670 return new SByteConstant ((sbyte) Value, Location);
672 if (target_type == TypeManager.ushort_type) {
673 if (in_checked_context && Value < 0)
674 throw new OverflowException ();
676 return new UShortConstant ((ushort) Value, Location);
678 if (target_type == TypeManager.int32_type)
679 return new IntConstant ((int) Value, Location);
680 if (target_type == TypeManager.uint32_type) {
681 if (in_checked_context && Value < 0)
682 throw new OverflowException ();
683 return new UIntConstant ((uint) Value, Location);
685 if (target_type == TypeManager.int64_type)
686 return new LongConstant ((long) Value, Location);
687 if (target_type == TypeManager.uint64_type) {
688 if (in_checked_context && Value < 0)
689 throw new OverflowException ();
690 return new ULongConstant ((ulong) Value, Location);
692 if (target_type == TypeManager.float_type)
693 return new FloatConstant ((float) Value, Location);
694 if (target_type == TypeManager.double_type)
695 return new DoubleConstant ((double) Value, Location);
696 if (target_type == TypeManager.char_type) {
697 if (in_checked_context){
698 if (Value < Char.MinValue)
699 throw new OverflowException ();
701 return new CharConstant ((char) Value, Location);
703 if (target_type == TypeManager.decimal_type)
704 return new DecimalConstant ((decimal) Value, Location);
711 public class UShortConstant : IntegralConstant {
712 public readonly ushort Value;
714 public UShortConstant (ushort v, Location loc):
717 type = TypeManager.ushort_type;
718 eclass = ExprClass.Value;
722 public override void Emit (EmitContext ec)
724 IntLiteral.EmitInt (ec.ig, Value);
727 public override string AsString ()
729 return Value.ToString ();
732 public override object GetValue ()
737 public override Constant Increment ()
739 return new UShortConstant (checked((ushort)(Value + 1)), loc);
742 public override bool IsDefaultValue {
748 public override bool IsNegative {
754 public override bool IsZeroInteger {
755 get { return Value == 0; }
758 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
760 if (target_type == TypeManager.byte_type) {
761 if (in_checked_context){
762 if (Value > Byte.MaxValue)
763 throw new OverflowException ();
765 return new ByteConstant ((byte) Value, Location);
767 if (target_type == TypeManager.sbyte_type) {
768 if (in_checked_context){
769 if (Value > SByte.MaxValue)
770 throw new OverflowException ();
772 return new SByteConstant ((sbyte) Value, Location);
774 if (target_type == TypeManager.short_type) {
775 if (in_checked_context){
776 if (Value > Int16.MaxValue)
777 throw new OverflowException ();
779 return new ShortConstant ((short) Value, Location);
781 if (target_type == TypeManager.int32_type)
782 return new IntConstant ((int) Value, Location);
783 if (target_type == TypeManager.uint32_type)
784 return new UIntConstant ((uint) Value, Location);
785 if (target_type == TypeManager.int64_type)
786 return new LongConstant ((long) Value, Location);
787 if (target_type == TypeManager.uint64_type)
788 return new ULongConstant ((ulong) Value, Location);
789 if (target_type == TypeManager.float_type)
790 return new FloatConstant ((float) Value, Location);
791 if (target_type == TypeManager.double_type)
792 return new DoubleConstant ((double) Value, Location);
793 if (target_type == TypeManager.char_type) {
794 if (in_checked_context){
795 if (Value > Char.MaxValue)
796 throw new OverflowException ();
798 return new CharConstant ((char) Value, Location);
800 if (target_type == TypeManager.decimal_type)
801 return new DecimalConstant ((decimal) Value, Location);
807 public class IntConstant : IntegralConstant {
808 public readonly int Value;
810 public IntConstant (int v, Location loc):
813 type = TypeManager.int32_type;
814 eclass = ExprClass.Value;
818 static public void EmitInt (ILGenerator ig, int i)
822 ig.Emit (OpCodes.Ldc_I4_M1);
826 ig.Emit (OpCodes.Ldc_I4_0);
830 ig.Emit (OpCodes.Ldc_I4_1);
834 ig.Emit (OpCodes.Ldc_I4_2);
838 ig.Emit (OpCodes.Ldc_I4_3);
842 ig.Emit (OpCodes.Ldc_I4_4);
846 ig.Emit (OpCodes.Ldc_I4_5);
850 ig.Emit (OpCodes.Ldc_I4_6);
854 ig.Emit (OpCodes.Ldc_I4_7);
858 ig.Emit (OpCodes.Ldc_I4_8);
862 if (i >= -128 && i <= 127){
863 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
865 ig.Emit (OpCodes.Ldc_I4, i);
870 public override void Emit (EmitContext ec)
872 EmitInt (ec.ig, Value);
875 public override string AsString ()
877 return Value.ToString ();
880 public override object GetValue ()
885 public override Constant Increment ()
887 return new IntConstant (checked(Value + 1), loc);
890 public override bool IsDefaultValue {
896 public override bool IsNegative {
902 public override bool IsZeroInteger {
903 get { return Value == 0; }
906 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
908 if (target_type == TypeManager.byte_type) {
909 if (in_checked_context){
910 if (Value < Byte.MinValue || Value > Byte.MaxValue)
911 throw new OverflowException ();
913 return new ByteConstant ((byte) Value, Location);
915 if (target_type == TypeManager.sbyte_type) {
916 if (in_checked_context){
917 if (Value < SByte.MinValue || Value > SByte.MaxValue)
918 throw new OverflowException ();
920 return new SByteConstant ((sbyte) Value, Location);
922 if (target_type == TypeManager.short_type) {
923 if (in_checked_context){
924 if (Value < Int16.MinValue || Value > Int16.MaxValue)
925 throw new OverflowException ();
927 return new ShortConstant ((short) Value, Location);
929 if (target_type == TypeManager.ushort_type) {
930 if (in_checked_context){
931 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
932 throw new OverflowException ();
934 return new UShortConstant ((ushort) Value, Location);
936 if (target_type == TypeManager.uint32_type) {
937 if (in_checked_context){
938 if (Value < UInt32.MinValue)
939 throw new OverflowException ();
941 return new UIntConstant ((uint) Value, Location);
943 if (target_type == TypeManager.int64_type)
944 return new LongConstant ((long) Value, Location);
945 if (target_type == TypeManager.uint64_type) {
946 if (in_checked_context && Value < 0)
947 throw new OverflowException ();
948 return new ULongConstant ((ulong) Value, Location);
950 if (target_type == TypeManager.float_type)
951 return new FloatConstant ((float) Value, Location);
952 if (target_type == TypeManager.double_type)
953 return new DoubleConstant ((double) Value, Location);
954 if (target_type == TypeManager.char_type) {
955 if (in_checked_context){
956 if (Value < Char.MinValue || Value > Char.MaxValue)
957 throw new OverflowException ();
959 return new CharConstant ((char) Value, Location);
961 if (target_type == TypeManager.decimal_type)
962 return new DecimalConstant ((decimal) Value, Location);
967 public override Constant ConvertImplicitly (Type type)
969 if (this.type == type)
972 Constant c = TryImplicitIntConversion (type);
976 return base.ConvertImplicitly (type);
980 /// Attempts to perform an implicit constant conversion of the IntConstant
981 /// into a different data type using casts (See Implicit Constant
982 /// Expression Conversions)
984 Constant TryImplicitIntConversion (Type target_type)
986 if (target_type == TypeManager.sbyte_type) {
987 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
988 return new SByteConstant ((sbyte) Value, loc);
990 else if (target_type == TypeManager.byte_type) {
991 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
992 return new ByteConstant ((byte) Value, loc);
994 else if (target_type == TypeManager.short_type) {
995 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
996 return new ShortConstant ((short) Value, loc);
998 else if (target_type == TypeManager.ushort_type) {
999 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1000 return new UShortConstant ((ushort) Value, loc);
1002 else if (target_type == TypeManager.uint32_type) {
1004 return new UIntConstant ((uint) Value, loc);
1006 else if (target_type == TypeManager.uint64_type) {
1008 // we can optimize this case: a positive int32
1009 // always fits on a uint64. But we need an opcode
1013 return new ULongConstant ((ulong) Value, loc);
1015 else if (target_type == TypeManager.double_type)
1016 return new DoubleConstant ((double) Value, loc);
1017 else if (target_type == TypeManager.float_type)
1018 return new FloatConstant ((float) Value, loc);
1024 public class UIntConstant : IntegralConstant {
1025 public readonly uint Value;
1027 public UIntConstant (uint v, Location loc):
1030 type = TypeManager.uint32_type;
1031 eclass = ExprClass.Value;
1035 public override void Emit (EmitContext ec)
1037 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1040 public override string AsString ()
1042 return Value.ToString ();
1045 public override object GetValue ()
1050 public override Constant Increment ()
1052 return new UIntConstant (checked(Value + 1), loc);
1055 public override bool IsDefaultValue {
1061 public override bool IsNegative {
1067 public override bool IsZeroInteger {
1068 get { return Value == 0; }
1071 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1073 if (target_type == TypeManager.byte_type) {
1074 if (in_checked_context){
1075 if (Value < Char.MinValue || Value > Char.MaxValue)
1076 throw new OverflowException ();
1078 return new ByteConstant ((byte) Value, Location);
1080 if (target_type == TypeManager.sbyte_type) {
1081 if (in_checked_context){
1082 if (Value > SByte.MaxValue)
1083 throw new OverflowException ();
1085 return new SByteConstant ((sbyte) Value, Location);
1087 if (target_type == TypeManager.short_type) {
1088 if (in_checked_context){
1089 if (Value > Int16.MaxValue)
1090 throw new OverflowException ();
1092 return new ShortConstant ((short) Value, Location);
1094 if (target_type == TypeManager.ushort_type) {
1095 if (in_checked_context){
1096 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1097 throw new OverflowException ();
1099 return new UShortConstant ((ushort) Value, Location);
1101 if (target_type == TypeManager.int32_type) {
1102 if (in_checked_context){
1103 if (Value > Int32.MaxValue)
1104 throw new OverflowException ();
1106 return new IntConstant ((int) Value, Location);
1108 if (target_type == TypeManager.int64_type)
1109 return new LongConstant ((long) Value, Location);
1110 if (target_type == TypeManager.uint64_type)
1111 return new ULongConstant ((ulong) Value, Location);
1112 if (target_type == TypeManager.float_type)
1113 return new FloatConstant ((float) Value, Location);
1114 if (target_type == TypeManager.double_type)
1115 return new DoubleConstant ((double) Value, Location);
1116 if (target_type == TypeManager.char_type) {
1117 if (in_checked_context){
1118 if (Value < Char.MinValue || Value > Char.MaxValue)
1119 throw new OverflowException ();
1121 return new CharConstant ((char) Value, Location);
1123 if (target_type == TypeManager.decimal_type)
1124 return new DecimalConstant ((decimal) Value, Location);
1131 public class LongConstant : IntegralConstant {
1132 public readonly long Value;
1134 public LongConstant (long v, Location loc):
1137 type = TypeManager.int64_type;
1138 eclass = ExprClass.Value;
1142 public override void Emit (EmitContext ec)
1144 EmitLong (ec.ig, Value);
1147 static public void EmitLong (ILGenerator ig, long l)
1149 if (l >= int.MinValue && l <= int.MaxValue) {
1150 IntLiteral.EmitInt (ig, unchecked ((int) l));
1151 ig.Emit (OpCodes.Conv_I8);
1154 ig.Emit (OpCodes.Ldc_I8, l);
1157 public override string AsString ()
1159 return Value.ToString ();
1162 public override object GetValue ()
1167 public override Constant Increment ()
1169 return new LongConstant (checked(Value + 1), loc);
1172 public override bool IsDefaultValue {
1178 public override bool IsNegative {
1184 public override bool IsZeroInteger {
1185 get { return Value == 0; }
1188 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1190 if (target_type == TypeManager.byte_type) {
1191 if (in_checked_context){
1192 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1193 throw new OverflowException ();
1195 return new ByteConstant ((byte) Value, Location);
1197 if (target_type == TypeManager.sbyte_type) {
1198 if (in_checked_context){
1199 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1200 throw new OverflowException ();
1202 return new SByteConstant ((sbyte) Value, Location);
1204 if (target_type == TypeManager.short_type) {
1205 if (in_checked_context){
1206 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1207 throw new OverflowException ();
1209 return new ShortConstant ((short) Value, Location);
1211 if (target_type == TypeManager.ushort_type) {
1212 if (in_checked_context){
1213 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1214 throw new OverflowException ();
1216 return new UShortConstant ((ushort) Value, Location);
1218 if (target_type == TypeManager.int32_type) {
1219 if (in_checked_context){
1220 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1221 throw new OverflowException ();
1223 return new IntConstant ((int) Value, Location);
1225 if (target_type == TypeManager.uint32_type) {
1226 if (in_checked_context){
1227 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1228 throw new OverflowException ();
1230 return new UIntConstant ((uint) Value, Location);
1232 if (target_type == TypeManager.uint64_type) {
1233 if (in_checked_context && Value < 0)
1234 throw new OverflowException ();
1235 return new ULongConstant ((ulong) Value, Location);
1237 if (target_type == TypeManager.float_type)
1238 return new FloatConstant ((float) Value, Location);
1239 if (target_type == TypeManager.double_type)
1240 return new DoubleConstant ((double) Value, Location);
1241 if (target_type == TypeManager.char_type) {
1242 if (in_checked_context){
1243 if (Value < Char.MinValue || Value > Char.MaxValue)
1244 throw new OverflowException ();
1246 return new CharConstant ((char) Value, Location);
1248 if (target_type == TypeManager.decimal_type)
1249 return new DecimalConstant ((decimal) Value, Location);
1254 public override Constant ConvertImplicitly (Type type)
1256 if (Value >= 0 && type == TypeManager.uint64_type) {
1257 return new ULongConstant ((ulong) Value, loc);
1260 return base.ConvertImplicitly (type);
1264 public class ULongConstant : IntegralConstant {
1265 public readonly ulong Value;
1267 public ULongConstant (ulong v, Location loc):
1270 type = TypeManager.uint64_type;
1271 eclass = ExprClass.Value;
1275 public override void Emit (EmitContext ec)
1277 ILGenerator ig = ec.ig;
1279 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1282 public override string AsString ()
1284 return Value.ToString ();
1287 public override object GetValue ()
1292 public override Constant Increment ()
1294 return new ULongConstant (checked(Value + 1), loc);
1297 public override bool IsDefaultValue {
1303 public override bool IsNegative {
1309 public override bool IsZeroInteger {
1310 get { return Value == 0; }
1313 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1315 if (target_type == TypeManager.byte_type) {
1316 if (in_checked_context && Value > Byte.MaxValue)
1317 throw new OverflowException ();
1318 return new ByteConstant ((byte) Value, Location);
1320 if (target_type == TypeManager.sbyte_type) {
1321 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1322 throw new OverflowException ();
1323 return new SByteConstant ((sbyte) Value, Location);
1325 if (target_type == TypeManager.short_type) {
1326 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1327 throw new OverflowException ();
1328 return new ShortConstant ((short) Value, Location);
1330 if (target_type == TypeManager.ushort_type) {
1331 if (in_checked_context && Value > UInt16.MaxValue)
1332 throw new OverflowException ();
1333 return new UShortConstant ((ushort) Value, Location);
1335 if (target_type == TypeManager.int32_type) {
1336 if (in_checked_context && Value > UInt32.MaxValue)
1337 throw new OverflowException ();
1338 return new IntConstant ((int) Value, Location);
1340 if (target_type == TypeManager.uint32_type) {
1341 if (in_checked_context && Value > UInt32.MaxValue)
1342 throw new OverflowException ();
1343 return new UIntConstant ((uint) Value, Location);
1345 if (target_type == TypeManager.int64_type) {
1346 if (in_checked_context && Value > Int64.MaxValue)
1347 throw new OverflowException ();
1348 return new LongConstant ((long) Value, Location);
1350 if (target_type == TypeManager.float_type)
1351 return new FloatConstant ((float) Value, Location);
1352 if (target_type == TypeManager.double_type)
1353 return new DoubleConstant ((double) Value, Location);
1354 if (target_type == TypeManager.char_type) {
1355 if (in_checked_context && Value > Char.MaxValue)
1356 throw new OverflowException ();
1357 return new CharConstant ((char) Value, Location);
1359 if (target_type == TypeManager.decimal_type)
1360 return new DecimalConstant ((decimal) Value, Location);
1367 public class FloatConstant : Constant {
1370 public FloatConstant (float v, Location loc):
1373 type = TypeManager.float_type;
1374 eclass = ExprClass.Value;
1378 public override void Emit (EmitContext ec)
1380 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1383 public override string AsString ()
1385 return Value.ToString ();
1388 public override object GetValue ()
1393 public override Constant Increment ()
1395 return new FloatConstant (checked(Value + 1), loc);
1398 public override bool IsDefaultValue {
1404 public override bool IsNegative {
1410 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1412 if (target_type == TypeManager.byte_type) {
1413 if (in_checked_context){
1414 if (Value < byte.MinValue || Value > byte.MaxValue)
1415 throw new OverflowException ();
1417 return new ByteConstant ((byte) Value, Location);
1419 if (target_type == TypeManager.sbyte_type) {
1420 if (in_checked_context){
1421 if (Value < sbyte.MinValue || Value > sbyte.MaxValue)
1422 throw new OverflowException ();
1424 return new SByteConstant ((sbyte) Value, Location);
1426 if (target_type == TypeManager.short_type) {
1427 if (in_checked_context){
1428 if (Value < short.MinValue || Value > short.MaxValue)
1429 throw new OverflowException ();
1431 return new ShortConstant ((short) Value, Location);
1433 if (target_type == TypeManager.ushort_type) {
1434 if (in_checked_context){
1435 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1436 throw new OverflowException ();
1438 return new UShortConstant ((ushort) Value, Location);
1440 if (target_type == TypeManager.int32_type) {
1441 if (in_checked_context){
1442 if (Value < int.MinValue || Value > int.MaxValue)
1443 throw new OverflowException ();
1445 return new IntConstant ((int) Value, Location);
1447 if (target_type == TypeManager.uint32_type) {
1448 if (in_checked_context){
1449 if (Value < uint.MinValue || Value > uint.MaxValue)
1450 throw new OverflowException ();
1452 return new UIntConstant ((uint) Value, Location);
1454 if (target_type == TypeManager.int64_type) {
1455 if (in_checked_context){
1456 if (Value < long.MinValue || Value > long.MaxValue)
1457 throw new OverflowException ();
1459 return new LongConstant ((long) Value, Location);
1461 if (target_type == TypeManager.uint64_type) {
1462 if (in_checked_context){
1463 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1464 throw new OverflowException ();
1466 return new ULongConstant ((ulong) Value, Location);
1468 if (target_type == TypeManager.double_type)
1469 return new DoubleConstant ((double) Value, Location);
1470 if (target_type == TypeManager.char_type) {
1471 if (in_checked_context){
1472 if (Value < (float) char.MinValue || Value > (float) char.MaxValue)
1473 throw new OverflowException ();
1475 return new CharConstant ((char) Value, Location);
1477 if (target_type == TypeManager.decimal_type)
1478 return new DecimalConstant ((decimal) Value, Location);
1485 public class DoubleConstant : Constant {
1486 public double Value;
1488 public DoubleConstant (double v, Location loc):
1491 type = TypeManager.double_type;
1492 eclass = ExprClass.Value;
1496 public override void Emit (EmitContext ec)
1498 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1501 public override string AsString ()
1503 return Value.ToString ();
1506 public override object GetValue ()
1511 public override Constant Increment ()
1513 return new DoubleConstant (checked(Value + 1), loc);
1516 public override bool IsDefaultValue {
1522 public override bool IsNegative {
1528 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1530 if (target_type == TypeManager.byte_type) {
1531 if (in_checked_context){
1532 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1533 throw new OverflowException ();
1535 return new ByteConstant ((byte) Value, Location);
1537 if (target_type == TypeManager.sbyte_type) {
1538 if (in_checked_context){
1539 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1540 throw new OverflowException ();
1542 return new SByteConstant ((sbyte) Value, Location);
1544 if (target_type == TypeManager.short_type) {
1545 if (in_checked_context){
1546 if (Value < short.MinValue || Value > short.MaxValue)
1547 throw new OverflowException ();
1549 return new ShortConstant ((short) Value, Location);
1551 if (target_type == TypeManager.ushort_type) {
1552 if (in_checked_context){
1553 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1554 throw new OverflowException ();
1556 return new UShortConstant ((ushort) Value, Location);
1558 if (target_type == TypeManager.int32_type) {
1559 if (in_checked_context){
1560 if (Value < int.MinValue || Value > int.MaxValue)
1561 throw new OverflowException ();
1563 return new IntConstant ((int) Value, Location);
1565 if (target_type == TypeManager.uint32_type) {
1566 if (in_checked_context){
1567 if (Value < uint.MinValue || Value > uint.MaxValue)
1568 throw new OverflowException ();
1570 return new UIntConstant ((uint) Value, Location);
1572 if (target_type == TypeManager.int64_type) {
1573 if (in_checked_context){
1574 if (Value < long.MinValue || Value > long.MaxValue)
1575 throw new OverflowException ();
1577 return new LongConstant ((long) Value, Location);
1579 if (target_type == TypeManager.uint64_type) {
1580 if (in_checked_context){
1581 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1582 throw new OverflowException ();
1584 return new ULongConstant ((ulong) Value, Location);
1586 if (target_type == TypeManager.float_type)
1587 return new FloatConstant ((float) Value, Location);
1588 if (target_type == TypeManager.char_type) {
1589 if (in_checked_context){
1590 if (Value < (double) char.MinValue || Value > (double) char.MaxValue)
1591 throw new OverflowException ();
1593 return new CharConstant ((char) Value, Location);
1595 if (target_type == TypeManager.decimal_type)
1596 return new DecimalConstant ((decimal) Value, Location);
1603 public class DecimalConstant : Constant {
1604 public readonly decimal Value;
1606 public DecimalConstant (decimal d, Location loc):
1609 type = TypeManager.decimal_type;
1610 eclass = ExprClass.Value;
1614 override public string AsString ()
1616 return Value.ToString ();
1619 public override object GetValue ()
1621 return (object) Value;
1624 public override void Emit (EmitContext ec)
1626 ILGenerator ig = ec.ig;
1628 int [] words = Decimal.GetBits (Value);
1629 int power = (words [3] >> 16) & 0xff;
1631 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1633 IntConstant.EmitInt (ig, (int)Value);
1634 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1640 // FIXME: we could optimize this, and call a better
1644 IntConstant.EmitInt (ig, words [0]);
1645 IntConstant.EmitInt (ig, words [1]);
1646 IntConstant.EmitInt (ig, words [2]);
1649 IntConstant.EmitInt (ig, words [3] >> 31);
1652 IntConstant.EmitInt (ig, power);
1654 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1657 public override Constant Increment ()
1659 return new DecimalConstant (checked (Value + 1), loc);
1662 public override bool IsDefaultValue {
1668 public override bool IsNegative {
1674 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1676 if (target_type == TypeManager.sbyte_type)
1677 return new SByteConstant ((sbyte)Value, loc);
1678 if (target_type == TypeManager.byte_type)
1679 return new ByteConstant ((byte)Value, loc);
1680 if (target_type == TypeManager.short_type)
1681 return new ShortConstant ((short)Value, loc);
1682 if (target_type == TypeManager.ushort_type)
1683 return new UShortConstant ((ushort)Value, loc);
1684 if (target_type == TypeManager.int32_type)
1685 return new IntConstant ((int)Value, loc);
1686 if (target_type == TypeManager.uint32_type)
1687 return new UIntConstant ((uint)Value, loc);
1688 if (target_type == TypeManager.int64_type)
1689 return new LongConstant ((long)Value, loc);
1690 if (target_type == TypeManager.uint64_type)
1691 return new ULongConstant ((ulong)Value, loc);
1692 if (target_type == TypeManager.char_type)
1693 return new CharConstant ((char)Value, loc);
1694 if (target_type == TypeManager.float_type)
1695 return new FloatConstant ((float)Value, loc);
1696 if (target_type == TypeManager.double_type)
1697 return new DoubleConstant ((double)Value, loc);
1704 public class StringConstant : Constant {
1705 public readonly string Value;
1707 public StringConstant (string s, Location loc):
1710 type = TypeManager.string_type;
1711 eclass = ExprClass.Value;
1715 // FIXME: Escape the string.
1716 override public string AsString ()
1718 return "\"" + Value + "\"";
1721 public override object GetValue ()
1726 public override void Emit (EmitContext ec)
1729 ec.ig.Emit (OpCodes.Ldnull);
1731 ec.ig.Emit (OpCodes.Ldstr, Value);
1734 public override Constant Increment ()
1736 throw new NotSupportedException ();
1739 public override bool IsDefaultValue {
1741 return Value == null;
1745 public override bool IsNegative {
1751 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1758 /// The value is constant, but when emitted has a side effect. This is
1759 /// used by BitwiseAnd to ensure that the second expression is invoked
1760 /// regardless of the value of the left side.
1763 public class SideEffectConstant : Constant {
1767 public SideEffectConstant (Constant left, Expression right, Location loc) : base (loc)
1771 eclass = ExprClass.Value;
1775 public override string AsString ()
1777 return left.AsString ();
1780 public override object GetValue ()
1782 return left.GetValue ();
1785 public override void Emit (EmitContext ec)
1789 ec.ig.Emit (OpCodes.Pop);
1792 public override bool IsDefaultValue {
1794 return left.IsDefaultValue;
1798 public override Constant Increment ()
1800 throw new NotSupportedException ();
1803 public override bool IsNegative {
1805 return left.IsNegative;
1809 public override bool IsZeroInteger {
1811 return left.IsZeroInteger;
1815 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1817 return left.ConvertExplicitly (in_checked_context, target_type);