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.GetEnumUnderlyingType (t);
143 return new EnumConstant (CreateConstant (real_type, v, loc), t);
145 if (v == null && !TypeManager.IsValueType (t))
146 return new EmptyConstantCast (new NullLiteral (loc), t);
148 throw new Exception ("Unknown type for constant (" + t +
152 public override Expression CreateExpressionTree (EmitContext ec)
154 ArrayList args = new ArrayList (2);
155 args.Add (new Argument (this));
156 args.Add (new Argument (
157 new TypeOf (new TypeExpression (type, loc), loc)));
159 return CreateExpressionFactoryCall ("Constant", args);
164 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
165 /// It throws OverflowException
167 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
168 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
171 /// Attempts to do a compile-time folding of a constant cast.
173 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
176 return TryReduce (ec, target_type);
178 catch (OverflowException) {
179 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
180 GetValue ().ToString (), TypeManager.CSharpName (target_type));
185 Constant TryReduce (EmitContext ec, Type target_type)
187 if (Type == target_type)
190 if (TypeManager.IsEnumType (target_type)) {
191 Constant c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type));
195 return new EnumConstant (c, target_type);
198 return ConvertExplicitly (ec.ConstantCheckState, target_type);
201 public abstract Constant Increment ();
204 /// Need to pass type as the constant can require a boxing
205 /// and in such case no optimization is possible
207 public bool IsDefaultInitializer (Type type)
210 return IsDefaultValue;
212 return Type == TypeManager.null_type;
215 public abstract bool IsDefaultValue {
219 public abstract bool IsNegative {
224 // Returns true iff 1) the stack type of this is one of Object,
225 // int32, int64 and 2) this == 0 or this == null.
227 public virtual bool IsZeroInteger {
228 get { return false; }
231 public override void EmitSideEffect (EmitContext ec)
236 protected override void CloneTo (CloneContext clonectx, Expression target)
238 // CloneTo: Nothing, we do not keep any state on this expression
242 public abstract class IntegralConstant : Constant {
243 protected IntegralConstant (Location loc) :
248 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
251 ConvertExplicitly (true, target);
252 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
256 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
257 GetValue ().ToString (), TypeManager.CSharpName (target));
262 public class BoolConstant : Constant {
263 public readonly bool Value;
265 public BoolConstant (bool val, Location loc):
268 type = TypeManager.bool_type;
269 eclass = ExprClass.Value;
274 override public string AsString ()
276 return Value ? "true" : "false";
279 public override object GetValue ()
281 return (object) Value;
285 public override void Emit (EmitContext ec)
288 ec.ig.Emit (OpCodes.Ldc_I4_1);
290 ec.ig.Emit (OpCodes.Ldc_I4_0);
293 public override Constant Increment ()
295 throw new NotSupportedException ();
298 public override bool IsDefaultValue {
304 public override bool IsNegative {
310 public override bool IsZeroInteger {
311 get { return Value == false; }
314 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
321 public class ByteConstant : IntegralConstant {
322 public readonly byte Value;
324 public ByteConstant (byte v, Location loc):
327 type = TypeManager.byte_type;
328 eclass = ExprClass.Value;
332 public override void Emit (EmitContext ec)
334 IntLiteral.EmitInt (ec.ig, Value);
337 public override string AsString ()
339 return Value.ToString ();
342 public override object GetValue ()
347 public override Constant Increment ()
349 return new ByteConstant (checked ((byte)(Value + 1)), loc);
352 public override bool IsDefaultValue {
358 public override bool IsNegative {
364 public override bool IsZeroInteger {
365 get { return Value == 0; }
368 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
370 if (target_type == TypeManager.sbyte_type) {
371 if (in_checked_context){
372 if (Value > SByte.MaxValue)
373 throw new OverflowException ();
375 return new SByteConstant ((sbyte) Value, Location);
377 if (target_type == TypeManager.short_type)
378 return new ShortConstant ((short) Value, Location);
379 if (target_type == TypeManager.ushort_type)
380 return new UShortConstant ((ushort) Value, Location);
381 if (target_type == TypeManager.int32_type)
382 return new IntConstant ((int) Value, Location);
383 if (target_type == TypeManager.uint32_type)
384 return new UIntConstant ((uint) Value, Location);
385 if (target_type == TypeManager.int64_type)
386 return new LongConstant ((long) Value, Location);
387 if (target_type == TypeManager.uint64_type)
388 return new ULongConstant ((ulong) Value, Location);
389 if (target_type == TypeManager.float_type)
390 return new FloatConstant ((float) Value, Location);
391 if (target_type == TypeManager.double_type)
392 return new DoubleConstant ((double) Value, Location);
393 if (target_type == TypeManager.char_type)
394 return new CharConstant ((char) Value, Location);
395 if (target_type == TypeManager.decimal_type)
396 return new DecimalConstant ((decimal) Value, Location);
403 public class CharConstant : Constant {
404 public readonly char Value;
406 public CharConstant (char v, Location loc):
409 type = TypeManager.char_type;
410 eclass = ExprClass.Value;
414 public override void Emit (EmitContext ec)
416 IntLiteral.EmitInt (ec.ig, Value);
419 static public string descape (char c)
445 return c.ToString ();
448 public override string AsString ()
450 return "\"" + descape (Value) + "\"";
453 public override object GetValue ()
458 public override Constant Increment ()
460 return new CharConstant (checked ((char)(Value + 1)), loc);
463 public override bool IsDefaultValue {
469 public override bool IsNegative {
475 public override bool IsZeroInteger {
476 get { return Value == '\0'; }
479 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
481 if (target_type == TypeManager.byte_type) {
482 if (in_checked_context){
483 if (Value < Byte.MinValue || Value > Byte.MaxValue)
484 throw new OverflowException ();
486 return new ByteConstant ((byte) Value, Location);
488 if (target_type == TypeManager.sbyte_type) {
489 if (in_checked_context){
490 if (Value > SByte.MaxValue)
491 throw new OverflowException ();
493 return new SByteConstant ((sbyte) Value, Location);
495 if (target_type == TypeManager.short_type) {
496 if (in_checked_context){
497 if (Value > Int16.MaxValue)
498 throw new OverflowException ();
500 return new ShortConstant ((short) Value, Location);
502 if (target_type == TypeManager.int32_type)
503 return new IntConstant ((int) Value, Location);
504 if (target_type == TypeManager.uint32_type)
505 return new UIntConstant ((uint) Value, Location);
506 if (target_type == TypeManager.int64_type)
507 return new LongConstant ((long) Value, Location);
508 if (target_type == TypeManager.uint64_type)
509 return new ULongConstant ((ulong) Value, Location);
510 if (target_type == TypeManager.float_type)
511 return new FloatConstant ((float) Value, Location);
512 if (target_type == TypeManager.double_type)
513 return new DoubleConstant ((double) Value, Location);
514 if (target_type == TypeManager.decimal_type)
515 return new DecimalConstant ((decimal) Value, Location);
522 public class SByteConstant : IntegralConstant {
523 public readonly sbyte Value;
525 public SByteConstant (sbyte v, Location loc):
528 type = TypeManager.sbyte_type;
529 eclass = ExprClass.Value;
533 public override void Emit (EmitContext ec)
535 IntLiteral.EmitInt (ec.ig, Value);
538 public override string AsString ()
540 return Value.ToString ();
543 public override object GetValue ()
548 public override Constant Increment ()
550 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
553 public override bool IsDefaultValue {
559 public override bool IsNegative {
565 public override bool IsZeroInteger {
566 get { return Value == 0; }
569 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
571 if (target_type == TypeManager.byte_type) {
572 if (in_checked_context && Value < 0)
573 throw new OverflowException ();
574 return new ByteConstant ((byte) Value, Location);
576 if (target_type == TypeManager.short_type)
577 return new ShortConstant ((short) Value, Location);
578 if (target_type == TypeManager.ushort_type) {
579 if (in_checked_context && Value < 0)
580 throw new OverflowException ();
581 return new UShortConstant ((ushort) Value, Location);
582 } if (target_type == TypeManager.int32_type)
583 return new IntConstant ((int) Value, Location);
584 if (target_type == TypeManager.uint32_type) {
585 if (in_checked_context && Value < 0)
586 throw new OverflowException ();
587 return new UIntConstant ((uint) Value, Location);
588 } if (target_type == TypeManager.int64_type)
589 return new LongConstant ((long) Value, Location);
590 if (target_type == TypeManager.uint64_type) {
591 if (in_checked_context && Value < 0)
592 throw new OverflowException ();
593 return new ULongConstant ((ulong) Value, Location);
595 if (target_type == TypeManager.float_type)
596 return new FloatConstant ((float) Value, Location);
597 if (target_type == TypeManager.double_type)
598 return new DoubleConstant ((double) Value, Location);
599 if (target_type == TypeManager.char_type) {
600 if (in_checked_context && Value < 0)
601 throw new OverflowException ();
602 return new CharConstant ((char) Value, Location);
604 if (target_type == TypeManager.decimal_type)
605 return new DecimalConstant ((decimal) Value, Location);
612 public class ShortConstant : IntegralConstant {
613 public readonly short Value;
615 public ShortConstant (short v, Location loc):
618 type = TypeManager.short_type;
619 eclass = ExprClass.Value;
623 public override void Emit (EmitContext ec)
625 IntLiteral.EmitInt (ec.ig, Value);
628 public override string AsString ()
630 return Value.ToString ();
633 public override object GetValue ()
638 public override Constant Increment ()
640 return new ShortConstant (checked((short)(Value + 1)), loc);
643 public override bool IsDefaultValue {
649 public override bool IsZeroInteger {
650 get { return Value == 0; }
653 public override bool IsNegative {
659 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
661 if (target_type == TypeManager.byte_type) {
662 if (in_checked_context){
663 if (Value < Byte.MinValue || Value > Byte.MaxValue)
664 throw new OverflowException ();
666 return new ByteConstant ((byte) Value, Location);
668 if (target_type == TypeManager.sbyte_type) {
669 if (in_checked_context){
670 if (Value < SByte.MinValue || Value > SByte.MaxValue)
671 throw new OverflowException ();
673 return new SByteConstant ((sbyte) Value, Location);
675 if (target_type == TypeManager.ushort_type) {
676 if (in_checked_context && Value < 0)
677 throw new OverflowException ();
679 return new UShortConstant ((ushort) Value, Location);
681 if (target_type == TypeManager.int32_type)
682 return new IntConstant ((int) Value, Location);
683 if (target_type == TypeManager.uint32_type) {
684 if (in_checked_context && Value < 0)
685 throw new OverflowException ();
686 return new UIntConstant ((uint) Value, Location);
688 if (target_type == TypeManager.int64_type)
689 return new LongConstant ((long) Value, Location);
690 if (target_type == TypeManager.uint64_type) {
691 if (in_checked_context && Value < 0)
692 throw new OverflowException ();
693 return new ULongConstant ((ulong) Value, Location);
695 if (target_type == TypeManager.float_type)
696 return new FloatConstant ((float) Value, Location);
697 if (target_type == TypeManager.double_type)
698 return new DoubleConstant ((double) Value, Location);
699 if (target_type == TypeManager.char_type) {
700 if (in_checked_context){
701 if (Value < Char.MinValue)
702 throw new OverflowException ();
704 return new CharConstant ((char) Value, Location);
706 if (target_type == TypeManager.decimal_type)
707 return new DecimalConstant ((decimal) Value, Location);
714 public class UShortConstant : IntegralConstant {
715 public readonly ushort Value;
717 public UShortConstant (ushort v, Location loc):
720 type = TypeManager.ushort_type;
721 eclass = ExprClass.Value;
725 public override void Emit (EmitContext ec)
727 IntLiteral.EmitInt (ec.ig, Value);
730 public override string AsString ()
732 return Value.ToString ();
735 public override object GetValue ()
740 public override Constant Increment ()
742 return new UShortConstant (checked((ushort)(Value + 1)), loc);
745 public override bool IsDefaultValue {
751 public override bool IsNegative {
757 public override bool IsZeroInteger {
758 get { return Value == 0; }
761 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
763 if (target_type == TypeManager.byte_type) {
764 if (in_checked_context){
765 if (Value > Byte.MaxValue)
766 throw new OverflowException ();
768 return new ByteConstant ((byte) Value, Location);
770 if (target_type == TypeManager.sbyte_type) {
771 if (in_checked_context){
772 if (Value > SByte.MaxValue)
773 throw new OverflowException ();
775 return new SByteConstant ((sbyte) Value, Location);
777 if (target_type == TypeManager.short_type) {
778 if (in_checked_context){
779 if (Value > Int16.MaxValue)
780 throw new OverflowException ();
782 return new ShortConstant ((short) Value, Location);
784 if (target_type == TypeManager.int32_type)
785 return new IntConstant ((int) Value, Location);
786 if (target_type == TypeManager.uint32_type)
787 return new UIntConstant ((uint) Value, Location);
788 if (target_type == TypeManager.int64_type)
789 return new LongConstant ((long) Value, Location);
790 if (target_type == TypeManager.uint64_type)
791 return new ULongConstant ((ulong) Value, Location);
792 if (target_type == TypeManager.float_type)
793 return new FloatConstant ((float) Value, Location);
794 if (target_type == TypeManager.double_type)
795 return new DoubleConstant ((double) Value, Location);
796 if (target_type == TypeManager.char_type) {
797 if (in_checked_context){
798 if (Value > Char.MaxValue)
799 throw new OverflowException ();
801 return new CharConstant ((char) Value, Location);
803 if (target_type == TypeManager.decimal_type)
804 return new DecimalConstant ((decimal) Value, Location);
810 public class IntConstant : IntegralConstant {
811 public readonly int Value;
813 public IntConstant (int v, Location loc):
816 type = TypeManager.int32_type;
817 eclass = ExprClass.Value;
821 static public void EmitInt (ILGenerator ig, int i)
825 ig.Emit (OpCodes.Ldc_I4_M1);
829 ig.Emit (OpCodes.Ldc_I4_0);
833 ig.Emit (OpCodes.Ldc_I4_1);
837 ig.Emit (OpCodes.Ldc_I4_2);
841 ig.Emit (OpCodes.Ldc_I4_3);
845 ig.Emit (OpCodes.Ldc_I4_4);
849 ig.Emit (OpCodes.Ldc_I4_5);
853 ig.Emit (OpCodes.Ldc_I4_6);
857 ig.Emit (OpCodes.Ldc_I4_7);
861 ig.Emit (OpCodes.Ldc_I4_8);
865 if (i >= -128 && i <= 127){
866 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
868 ig.Emit (OpCodes.Ldc_I4, i);
873 public override void Emit (EmitContext ec)
875 EmitInt (ec.ig, Value);
878 public override string AsString ()
880 return Value.ToString ();
883 public override object GetValue ()
888 public override Constant Increment ()
890 return new IntConstant (checked(Value + 1), loc);
893 public override bool IsDefaultValue {
899 public override bool IsNegative {
905 public override bool IsZeroInteger {
906 get { return Value == 0; }
909 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
911 if (target_type == TypeManager.byte_type) {
912 if (in_checked_context){
913 if (Value < Byte.MinValue || Value > Byte.MaxValue)
914 throw new OverflowException ();
916 return new ByteConstant ((byte) Value, Location);
918 if (target_type == TypeManager.sbyte_type) {
919 if (in_checked_context){
920 if (Value < SByte.MinValue || Value > SByte.MaxValue)
921 throw new OverflowException ();
923 return new SByteConstant ((sbyte) Value, Location);
925 if (target_type == TypeManager.short_type) {
926 if (in_checked_context){
927 if (Value < Int16.MinValue || Value > Int16.MaxValue)
928 throw new OverflowException ();
930 return new ShortConstant ((short) Value, Location);
932 if (target_type == TypeManager.ushort_type) {
933 if (in_checked_context){
934 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
935 throw new OverflowException ();
937 return new UShortConstant ((ushort) Value, Location);
939 if (target_type == TypeManager.uint32_type) {
940 if (in_checked_context){
941 if (Value < UInt32.MinValue)
942 throw new OverflowException ();
944 return new UIntConstant ((uint) Value, Location);
946 if (target_type == TypeManager.int64_type)
947 return new LongConstant ((long) Value, Location);
948 if (target_type == TypeManager.uint64_type) {
949 if (in_checked_context && Value < 0)
950 throw new OverflowException ();
951 return new ULongConstant ((ulong) Value, Location);
953 if (target_type == TypeManager.float_type)
954 return new FloatConstant ((float) Value, Location);
955 if (target_type == TypeManager.double_type)
956 return new DoubleConstant ((double) Value, Location);
957 if (target_type == TypeManager.char_type) {
958 if (in_checked_context){
959 if (Value < Char.MinValue || Value > Char.MaxValue)
960 throw new OverflowException ();
962 return new CharConstant ((char) Value, Location);
964 if (target_type == TypeManager.decimal_type)
965 return new DecimalConstant ((decimal) Value, Location);
970 public override Constant ConvertImplicitly (Type type)
972 if (this.type == type)
975 Constant c = TryImplicitIntConversion (type);
979 return base.ConvertImplicitly (type);
983 /// Attempts to perform an implicit constant conversion of the IntConstant
984 /// into a different data type using casts (See Implicit Constant
985 /// Expression Conversions)
987 Constant TryImplicitIntConversion (Type target_type)
989 if (target_type == TypeManager.sbyte_type) {
990 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
991 return new SByteConstant ((sbyte) Value, loc);
993 else if (target_type == TypeManager.byte_type) {
994 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
995 return new ByteConstant ((byte) Value, loc);
997 else if (target_type == TypeManager.short_type) {
998 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
999 return new ShortConstant ((short) Value, loc);
1001 else if (target_type == TypeManager.ushort_type) {
1002 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1003 return new UShortConstant ((ushort) Value, loc);
1005 else if (target_type == TypeManager.uint32_type) {
1007 return new UIntConstant ((uint) Value, loc);
1009 else if (target_type == TypeManager.uint64_type) {
1011 // we can optimize this case: a positive int32
1012 // always fits on a uint64. But we need an opcode
1016 return new ULongConstant ((ulong) Value, loc);
1018 else if (target_type == TypeManager.double_type)
1019 return new DoubleConstant ((double) Value, loc);
1020 else if (target_type == TypeManager.float_type)
1021 return new FloatConstant ((float) Value, loc);
1027 public class UIntConstant : IntegralConstant {
1028 public readonly uint Value;
1030 public UIntConstant (uint v, Location loc):
1033 type = TypeManager.uint32_type;
1034 eclass = ExprClass.Value;
1038 public override void Emit (EmitContext ec)
1040 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1043 public override string AsString ()
1045 return Value.ToString ();
1048 public override object GetValue ()
1053 public override Constant Increment ()
1055 return new UIntConstant (checked(Value + 1), loc);
1058 public override bool IsDefaultValue {
1064 public override bool IsNegative {
1070 public override bool IsZeroInteger {
1071 get { return Value == 0; }
1074 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1076 if (target_type == TypeManager.byte_type) {
1077 if (in_checked_context){
1078 if (Value < Char.MinValue || Value > Char.MaxValue)
1079 throw new OverflowException ();
1081 return new ByteConstant ((byte) Value, Location);
1083 if (target_type == TypeManager.sbyte_type) {
1084 if (in_checked_context){
1085 if (Value > SByte.MaxValue)
1086 throw new OverflowException ();
1088 return new SByteConstant ((sbyte) Value, Location);
1090 if (target_type == TypeManager.short_type) {
1091 if (in_checked_context){
1092 if (Value > Int16.MaxValue)
1093 throw new OverflowException ();
1095 return new ShortConstant ((short) Value, Location);
1097 if (target_type == TypeManager.ushort_type) {
1098 if (in_checked_context){
1099 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1100 throw new OverflowException ();
1102 return new UShortConstant ((ushort) Value, Location);
1104 if (target_type == TypeManager.int32_type) {
1105 if (in_checked_context){
1106 if (Value > Int32.MaxValue)
1107 throw new OverflowException ();
1109 return new IntConstant ((int) Value, Location);
1111 if (target_type == TypeManager.int64_type)
1112 return new LongConstant ((long) Value, Location);
1113 if (target_type == TypeManager.uint64_type)
1114 return new ULongConstant ((ulong) Value, Location);
1115 if (target_type == TypeManager.float_type)
1116 return new FloatConstant ((float) Value, Location);
1117 if (target_type == TypeManager.double_type)
1118 return new DoubleConstant ((double) Value, Location);
1119 if (target_type == TypeManager.char_type) {
1120 if (in_checked_context){
1121 if (Value < Char.MinValue || Value > Char.MaxValue)
1122 throw new OverflowException ();
1124 return new CharConstant ((char) Value, Location);
1126 if (target_type == TypeManager.decimal_type)
1127 return new DecimalConstant ((decimal) Value, Location);
1134 public class LongConstant : IntegralConstant {
1135 public readonly long Value;
1137 public LongConstant (long v, Location loc):
1140 type = TypeManager.int64_type;
1141 eclass = ExprClass.Value;
1145 public override void Emit (EmitContext ec)
1147 EmitLong (ec.ig, Value);
1150 static public void EmitLong (ILGenerator ig, long l)
1152 if (l >= int.MinValue && l <= int.MaxValue) {
1153 IntLiteral.EmitInt (ig, unchecked ((int) l));
1154 ig.Emit (OpCodes.Conv_I8);
1157 ig.Emit (OpCodes.Ldc_I8, l);
1160 public override string AsString ()
1162 return Value.ToString ();
1165 public override object GetValue ()
1170 public override Constant Increment ()
1172 return new LongConstant (checked(Value + 1), loc);
1175 public override bool IsDefaultValue {
1181 public override bool IsNegative {
1187 public override bool IsZeroInteger {
1188 get { return Value == 0; }
1191 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1193 if (target_type == TypeManager.byte_type) {
1194 if (in_checked_context){
1195 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1196 throw new OverflowException ();
1198 return new ByteConstant ((byte) Value, Location);
1200 if (target_type == TypeManager.sbyte_type) {
1201 if (in_checked_context){
1202 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1203 throw new OverflowException ();
1205 return new SByteConstant ((sbyte) Value, Location);
1207 if (target_type == TypeManager.short_type) {
1208 if (in_checked_context){
1209 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1210 throw new OverflowException ();
1212 return new ShortConstant ((short) Value, Location);
1214 if (target_type == TypeManager.ushort_type) {
1215 if (in_checked_context){
1216 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1217 throw new OverflowException ();
1219 return new UShortConstant ((ushort) Value, Location);
1221 if (target_type == TypeManager.int32_type) {
1222 if (in_checked_context){
1223 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1224 throw new OverflowException ();
1226 return new IntConstant ((int) Value, Location);
1228 if (target_type == TypeManager.uint32_type) {
1229 if (in_checked_context){
1230 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1231 throw new OverflowException ();
1233 return new UIntConstant ((uint) Value, Location);
1235 if (target_type == TypeManager.uint64_type) {
1236 if (in_checked_context && Value < 0)
1237 throw new OverflowException ();
1238 return new ULongConstant ((ulong) Value, Location);
1240 if (target_type == TypeManager.float_type)
1241 return new FloatConstant ((float) Value, Location);
1242 if (target_type == TypeManager.double_type)
1243 return new DoubleConstant ((double) Value, Location);
1244 if (target_type == TypeManager.char_type) {
1245 if (in_checked_context){
1246 if (Value < Char.MinValue || Value > Char.MaxValue)
1247 throw new OverflowException ();
1249 return new CharConstant ((char) Value, Location);
1251 if (target_type == TypeManager.decimal_type)
1252 return new DecimalConstant ((decimal) Value, Location);
1257 public override Constant ConvertImplicitly (Type type)
1259 if (Value >= 0 && type == TypeManager.uint64_type) {
1260 return new ULongConstant ((ulong) Value, loc);
1263 return base.ConvertImplicitly (type);
1267 public class ULongConstant : IntegralConstant {
1268 public readonly ulong Value;
1270 public ULongConstant (ulong v, Location loc):
1273 type = TypeManager.uint64_type;
1274 eclass = ExprClass.Value;
1278 public override void Emit (EmitContext ec)
1280 ILGenerator ig = ec.ig;
1282 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1285 public override string AsString ()
1287 return Value.ToString ();
1290 public override object GetValue ()
1295 public override Constant Increment ()
1297 return new ULongConstant (checked(Value + 1), loc);
1300 public override bool IsDefaultValue {
1306 public override bool IsNegative {
1312 public override bool IsZeroInteger {
1313 get { return Value == 0; }
1316 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1318 if (target_type == TypeManager.byte_type) {
1319 if (in_checked_context && Value > Byte.MaxValue)
1320 throw new OverflowException ();
1321 return new ByteConstant ((byte) Value, Location);
1323 if (target_type == TypeManager.sbyte_type) {
1324 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1325 throw new OverflowException ();
1326 return new SByteConstant ((sbyte) Value, Location);
1328 if (target_type == TypeManager.short_type) {
1329 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1330 throw new OverflowException ();
1331 return new ShortConstant ((short) Value, Location);
1333 if (target_type == TypeManager.ushort_type) {
1334 if (in_checked_context && Value > UInt16.MaxValue)
1335 throw new OverflowException ();
1336 return new UShortConstant ((ushort) Value, Location);
1338 if (target_type == TypeManager.int32_type) {
1339 if (in_checked_context && Value > UInt32.MaxValue)
1340 throw new OverflowException ();
1341 return new IntConstant ((int) Value, Location);
1343 if (target_type == TypeManager.uint32_type) {
1344 if (in_checked_context && Value > UInt32.MaxValue)
1345 throw new OverflowException ();
1346 return new UIntConstant ((uint) Value, Location);
1348 if (target_type == TypeManager.int64_type) {
1349 if (in_checked_context && Value > Int64.MaxValue)
1350 throw new OverflowException ();
1351 return new LongConstant ((long) Value, Location);
1353 if (target_type == TypeManager.float_type)
1354 return new FloatConstant ((float) Value, Location);
1355 if (target_type == TypeManager.double_type)
1356 return new DoubleConstant ((double) Value, Location);
1357 if (target_type == TypeManager.char_type) {
1358 if (in_checked_context && Value > Char.MaxValue)
1359 throw new OverflowException ();
1360 return new CharConstant ((char) Value, Location);
1362 if (target_type == TypeManager.decimal_type)
1363 return new DecimalConstant ((decimal) Value, Location);
1370 public class FloatConstant : Constant {
1373 public FloatConstant (float v, Location loc):
1376 type = TypeManager.float_type;
1377 eclass = ExprClass.Value;
1381 public override void Emit (EmitContext ec)
1383 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1386 public override string AsString ()
1388 return Value.ToString ();
1391 public override object GetValue ()
1396 public override Constant Increment ()
1398 return new FloatConstant (checked(Value + 1), loc);
1401 public override bool IsDefaultValue {
1407 public override bool IsNegative {
1413 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1415 if (target_type == TypeManager.byte_type) {
1416 if (in_checked_context){
1417 if (Value < byte.MinValue || Value > byte.MaxValue)
1418 throw new OverflowException ();
1420 return new ByteConstant ((byte) Value, Location);
1422 if (target_type == TypeManager.sbyte_type) {
1423 if (in_checked_context){
1424 if (Value < sbyte.MinValue || Value > sbyte.MaxValue)
1425 throw new OverflowException ();
1427 return new SByteConstant ((sbyte) Value, Location);
1429 if (target_type == TypeManager.short_type) {
1430 if (in_checked_context){
1431 if (Value < short.MinValue || Value > short.MaxValue)
1432 throw new OverflowException ();
1434 return new ShortConstant ((short) Value, Location);
1436 if (target_type == TypeManager.ushort_type) {
1437 if (in_checked_context){
1438 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1439 throw new OverflowException ();
1441 return new UShortConstant ((ushort) Value, Location);
1443 if (target_type == TypeManager.int32_type) {
1444 if (in_checked_context){
1445 if (Value < int.MinValue || Value > int.MaxValue)
1446 throw new OverflowException ();
1448 return new IntConstant ((int) Value, Location);
1450 if (target_type == TypeManager.uint32_type) {
1451 if (in_checked_context){
1452 if (Value < uint.MinValue || Value > uint.MaxValue)
1453 throw new OverflowException ();
1455 return new UIntConstant ((uint) Value, Location);
1457 if (target_type == TypeManager.int64_type) {
1458 if (in_checked_context){
1459 if (Value < long.MinValue || Value > long.MaxValue)
1460 throw new OverflowException ();
1462 return new LongConstant ((long) Value, Location);
1464 if (target_type == TypeManager.uint64_type) {
1465 if (in_checked_context){
1466 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1467 throw new OverflowException ();
1469 return new ULongConstant ((ulong) Value, Location);
1471 if (target_type == TypeManager.double_type)
1472 return new DoubleConstant ((double) Value, Location);
1473 if (target_type == TypeManager.char_type) {
1474 if (in_checked_context){
1475 if (Value < (float) char.MinValue || Value > (float) char.MaxValue)
1476 throw new OverflowException ();
1478 return new CharConstant ((char) Value, Location);
1480 if (target_type == TypeManager.decimal_type)
1481 return new DecimalConstant ((decimal) Value, Location);
1488 public class DoubleConstant : Constant {
1489 public double Value;
1491 public DoubleConstant (double v, Location loc):
1494 type = TypeManager.double_type;
1495 eclass = ExprClass.Value;
1499 public override void Emit (EmitContext ec)
1501 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1504 public override string AsString ()
1506 return Value.ToString ();
1509 public override object GetValue ()
1514 public override Constant Increment ()
1516 return new DoubleConstant (checked(Value + 1), loc);
1519 public override bool IsDefaultValue {
1525 public override bool IsNegative {
1531 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1533 if (target_type == TypeManager.byte_type) {
1534 if (in_checked_context){
1535 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1536 throw new OverflowException ();
1538 return new ByteConstant ((byte) Value, Location);
1540 if (target_type == TypeManager.sbyte_type) {
1541 if (in_checked_context){
1542 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1543 throw new OverflowException ();
1545 return new SByteConstant ((sbyte) Value, Location);
1547 if (target_type == TypeManager.short_type) {
1548 if (in_checked_context){
1549 if (Value < short.MinValue || Value > short.MaxValue)
1550 throw new OverflowException ();
1552 return new ShortConstant ((short) Value, Location);
1554 if (target_type == TypeManager.ushort_type) {
1555 if (in_checked_context){
1556 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1557 throw new OverflowException ();
1559 return new UShortConstant ((ushort) Value, Location);
1561 if (target_type == TypeManager.int32_type) {
1562 if (in_checked_context){
1563 if (Value < int.MinValue || Value > int.MaxValue)
1564 throw new OverflowException ();
1566 return new IntConstant ((int) Value, Location);
1568 if (target_type == TypeManager.uint32_type) {
1569 if (in_checked_context){
1570 if (Value < uint.MinValue || Value > uint.MaxValue)
1571 throw new OverflowException ();
1573 return new UIntConstant ((uint) Value, Location);
1575 if (target_type == TypeManager.int64_type) {
1576 if (in_checked_context){
1577 if (Value < long.MinValue || Value > long.MaxValue)
1578 throw new OverflowException ();
1580 return new LongConstant ((long) Value, Location);
1582 if (target_type == TypeManager.uint64_type) {
1583 if (in_checked_context){
1584 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1585 throw new OverflowException ();
1587 return new ULongConstant ((ulong) Value, Location);
1589 if (target_type == TypeManager.float_type)
1590 return new FloatConstant ((float) Value, Location);
1591 if (target_type == TypeManager.char_type) {
1592 if (in_checked_context){
1593 if (Value < (double) char.MinValue || Value > (double) char.MaxValue)
1594 throw new OverflowException ();
1596 return new CharConstant ((char) Value, Location);
1598 if (target_type == TypeManager.decimal_type)
1599 return new DecimalConstant ((decimal) Value, Location);
1606 public class DecimalConstant : Constant {
1607 public readonly decimal Value;
1609 public DecimalConstant (decimal d, Location loc):
1612 type = TypeManager.decimal_type;
1613 eclass = ExprClass.Value;
1617 override public string AsString ()
1619 return Value.ToString ();
1622 public override object GetValue ()
1624 return (object) Value;
1627 public override void Emit (EmitContext ec)
1629 ILGenerator ig = ec.ig;
1631 int [] words = Decimal.GetBits (Value);
1632 int power = (words [3] >> 16) & 0xff;
1634 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1636 if (TypeManager.void_decimal_ctor_int_arg == null) {
1637 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1638 TypeManager.decimal_type, loc, TypeManager.int32_type);
1640 if (TypeManager.void_decimal_ctor_int_arg == null)
1644 IntConstant.EmitInt (ig, (int)Value);
1645 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1651 // FIXME: we could optimize this, and call a better
1655 IntConstant.EmitInt (ig, words [0]);
1656 IntConstant.EmitInt (ig, words [1]);
1657 IntConstant.EmitInt (ig, words [2]);
1660 IntConstant.EmitInt (ig, words [3] >> 31);
1663 IntConstant.EmitInt (ig, power);
1665 if (TypeManager.void_decimal_ctor_five_args == null) {
1666 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1667 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1668 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1670 if (TypeManager.void_decimal_ctor_five_args == null)
1674 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1677 public override Constant Increment ()
1679 return new DecimalConstant (checked (Value + 1), loc);
1682 public override bool IsDefaultValue {
1688 public override bool IsNegative {
1694 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1696 if (target_type == TypeManager.sbyte_type)
1697 return new SByteConstant ((sbyte)Value, loc);
1698 if (target_type == TypeManager.byte_type)
1699 return new ByteConstant ((byte)Value, loc);
1700 if (target_type == TypeManager.short_type)
1701 return new ShortConstant ((short)Value, loc);
1702 if (target_type == TypeManager.ushort_type)
1703 return new UShortConstant ((ushort)Value, loc);
1704 if (target_type == TypeManager.int32_type)
1705 return new IntConstant ((int)Value, loc);
1706 if (target_type == TypeManager.uint32_type)
1707 return new UIntConstant ((uint)Value, loc);
1708 if (target_type == TypeManager.int64_type)
1709 return new LongConstant ((long)Value, loc);
1710 if (target_type == TypeManager.uint64_type)
1711 return new ULongConstant ((ulong)Value, loc);
1712 if (target_type == TypeManager.char_type)
1713 return new CharConstant ((char)Value, loc);
1714 if (target_type == TypeManager.float_type)
1715 return new FloatConstant ((float)Value, loc);
1716 if (target_type == TypeManager.double_type)
1717 return new DoubleConstant ((double)Value, loc);
1724 public class StringConstant : Constant {
1725 public readonly string Value;
1727 public StringConstant (string s, Location loc):
1730 type = TypeManager.string_type;
1731 eclass = ExprClass.Value;
1735 // FIXME: Escape the string.
1736 override public string AsString ()
1738 return "\"" + Value + "\"";
1741 public override object GetValue ()
1746 public override void Emit (EmitContext ec)
1749 ec.ig.Emit (OpCodes.Ldnull);
1751 ec.ig.Emit (OpCodes.Ldstr, Value);
1754 public override Constant Increment ()
1756 throw new NotSupportedException ();
1759 public override bool IsDefaultValue {
1761 return Value == null;
1765 public override bool IsNegative {
1771 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1778 /// The value is constant, but when emitted has a side effect. This is
1779 /// used by BitwiseAnd to ensure that the second expression is invoked
1780 /// regardless of the value of the left side.
1783 public class SideEffectConstant : Constant {
1784 public Constant value;
1785 Expression side_effect;
1787 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
1790 while (side_effect is SideEffectConstant)
1791 side_effect = ((SideEffectConstant) side_effect).side_effect;
1792 this.side_effect = side_effect;
1793 eclass = ExprClass.Value;
1797 public override string AsString ()
1799 return value.AsString ();
1802 public override object GetValue ()
1804 return value.GetValue ();
1807 public override void Emit (EmitContext ec)
1809 side_effect.EmitSideEffect (ec);
1813 public override void EmitSideEffect (EmitContext ec)
1815 side_effect.EmitSideEffect (ec);
1818 public override bool IsDefaultValue {
1819 get { return value.IsDefaultValue; }
1822 public override Constant Increment ()
1824 throw new NotSupportedException ();
1827 public override bool IsNegative {
1828 get { return value.IsNegative; }
1831 public override bool IsZeroInteger {
1832 get { return value.IsZeroInteger; }
1835 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1837 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
1838 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);