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 protected override void CloneTo (CloneContext clonectx, Expression target)
233 // CloneTo: Nothing, we do not keep any state on this expression
237 public abstract class IntegralConstant : Constant {
238 protected IntegralConstant (Location loc) :
243 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
246 ConvertExplicitly (true, target);
247 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
251 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
252 GetValue ().ToString (), TypeManager.CSharpName (target));
257 public class BoolConstant : Constant {
258 public readonly bool Value;
260 public BoolConstant (bool val, Location loc):
263 type = TypeManager.bool_type;
264 eclass = ExprClass.Value;
269 override public string AsString ()
271 return Value ? "true" : "false";
274 public override object GetValue ()
276 return (object) Value;
280 public override void Emit (EmitContext ec)
283 ec.ig.Emit (OpCodes.Ldc_I4_1);
285 ec.ig.Emit (OpCodes.Ldc_I4_0);
288 public override Constant Increment ()
290 throw new NotSupportedException ();
293 public override bool IsDefaultValue {
299 public override bool IsNegative {
305 public override bool IsZeroInteger {
306 get { return Value == false; }
309 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
316 public class ByteConstant : IntegralConstant {
317 public readonly byte Value;
319 public ByteConstant (byte v, Location loc):
322 type = TypeManager.byte_type;
323 eclass = ExprClass.Value;
327 public override void Emit (EmitContext ec)
329 IntLiteral.EmitInt (ec.ig, Value);
332 public override string AsString ()
334 return Value.ToString ();
337 public override object GetValue ()
342 public override Constant Increment ()
344 return new ByteConstant (checked ((byte)(Value + 1)), loc);
347 public override bool IsDefaultValue {
353 public override bool IsNegative {
359 public override bool IsZeroInteger {
360 get { return Value == 0; }
363 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
365 if (target_type == TypeManager.sbyte_type) {
366 if (in_checked_context){
367 if (Value > SByte.MaxValue)
368 throw new OverflowException ();
370 return new SByteConstant ((sbyte) Value, Location);
372 if (target_type == TypeManager.short_type)
373 return new ShortConstant ((short) Value, Location);
374 if (target_type == TypeManager.ushort_type)
375 return new UShortConstant ((ushort) Value, Location);
376 if (target_type == TypeManager.int32_type)
377 return new IntConstant ((int) Value, Location);
378 if (target_type == TypeManager.uint32_type)
379 return new UIntConstant ((uint) Value, Location);
380 if (target_type == TypeManager.int64_type)
381 return new LongConstant ((long) Value, Location);
382 if (target_type == TypeManager.uint64_type)
383 return new ULongConstant ((ulong) Value, Location);
384 if (target_type == TypeManager.float_type)
385 return new FloatConstant ((float) Value, Location);
386 if (target_type == TypeManager.double_type)
387 return new DoubleConstant ((double) Value, Location);
388 if (target_type == TypeManager.char_type)
389 return new CharConstant ((char) Value, Location);
390 if (target_type == TypeManager.decimal_type)
391 return new DecimalConstant ((decimal) Value, Location);
398 public class CharConstant : Constant {
399 public readonly char Value;
401 public CharConstant (char v, Location loc):
404 type = TypeManager.char_type;
405 eclass = ExprClass.Value;
409 public override void Emit (EmitContext ec)
411 IntLiteral.EmitInt (ec.ig, Value);
414 static public string descape (char c)
440 return c.ToString ();
443 public override string AsString ()
445 return "\"" + descape (Value) + "\"";
448 public override object GetValue ()
453 public override Constant Increment ()
455 return new CharConstant (checked ((char)(Value + 1)), loc);
458 public override bool IsDefaultValue {
464 public override bool IsNegative {
470 public override bool IsZeroInteger {
471 get { return Value == '\0'; }
474 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
476 if (target_type == TypeManager.byte_type) {
477 if (in_checked_context){
478 if (Value < Byte.MinValue || Value > Byte.MaxValue)
479 throw new OverflowException ();
481 return new ByteConstant ((byte) Value, Location);
483 if (target_type == TypeManager.sbyte_type) {
484 if (in_checked_context){
485 if (Value > SByte.MaxValue)
486 throw new OverflowException ();
488 return new SByteConstant ((sbyte) Value, Location);
490 if (target_type == TypeManager.short_type) {
491 if (in_checked_context){
492 if (Value > Int16.MaxValue)
493 throw new OverflowException ();
495 return new ShortConstant ((short) Value, Location);
497 if (target_type == TypeManager.int32_type)
498 return new IntConstant ((int) Value, Location);
499 if (target_type == TypeManager.uint32_type)
500 return new UIntConstant ((uint) Value, Location);
501 if (target_type == TypeManager.int64_type)
502 return new LongConstant ((long) Value, Location);
503 if (target_type == TypeManager.uint64_type)
504 return new ULongConstant ((ulong) Value, Location);
505 if (target_type == TypeManager.float_type)
506 return new FloatConstant ((float) Value, Location);
507 if (target_type == TypeManager.double_type)
508 return new DoubleConstant ((double) Value, Location);
509 if (target_type == TypeManager.decimal_type)
510 return new DecimalConstant ((decimal) Value, Location);
517 public class SByteConstant : IntegralConstant {
518 public readonly sbyte Value;
520 public SByteConstant (sbyte v, Location loc):
523 type = TypeManager.sbyte_type;
524 eclass = ExprClass.Value;
528 public override void Emit (EmitContext ec)
530 IntLiteral.EmitInt (ec.ig, Value);
533 public override string AsString ()
535 return Value.ToString ();
538 public override object GetValue ()
543 public override Constant Increment ()
545 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
548 public override bool IsDefaultValue {
554 public override bool IsNegative {
560 public override bool IsZeroInteger {
561 get { return Value == 0; }
564 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
566 if (target_type == TypeManager.byte_type) {
567 if (in_checked_context && Value < 0)
568 throw new OverflowException ();
569 return new ByteConstant ((byte) Value, Location);
571 if (target_type == TypeManager.short_type)
572 return new ShortConstant ((short) Value, Location);
573 if (target_type == TypeManager.ushort_type) {
574 if (in_checked_context && Value < 0)
575 throw new OverflowException ();
576 return new UShortConstant ((ushort) Value, Location);
577 } if (target_type == TypeManager.int32_type)
578 return new IntConstant ((int) Value, Location);
579 if (target_type == TypeManager.uint32_type) {
580 if (in_checked_context && Value < 0)
581 throw new OverflowException ();
582 return new UIntConstant ((uint) Value, Location);
583 } if (target_type == TypeManager.int64_type)
584 return new LongConstant ((long) Value, Location);
585 if (target_type == TypeManager.uint64_type) {
586 if (in_checked_context && Value < 0)
587 throw new OverflowException ();
588 return new ULongConstant ((ulong) Value, Location);
590 if (target_type == TypeManager.float_type)
591 return new FloatConstant ((float) Value, Location);
592 if (target_type == TypeManager.double_type)
593 return new DoubleConstant ((double) Value, Location);
594 if (target_type == TypeManager.char_type) {
595 if (in_checked_context && Value < 0)
596 throw new OverflowException ();
597 return new CharConstant ((char) Value, Location);
599 if (target_type == TypeManager.decimal_type)
600 return new DecimalConstant ((decimal) Value, Location);
607 public class ShortConstant : IntegralConstant {
608 public readonly short Value;
610 public ShortConstant (short v, Location loc):
613 type = TypeManager.short_type;
614 eclass = ExprClass.Value;
618 public override void Emit (EmitContext ec)
620 IntLiteral.EmitInt (ec.ig, Value);
623 public override string AsString ()
625 return Value.ToString ();
628 public override object GetValue ()
633 public override Constant Increment ()
635 return new ShortConstant (checked((short)(Value + 1)), loc);
638 public override bool IsDefaultValue {
644 public override bool IsZeroInteger {
645 get { return Value == 0; }
648 public override bool IsNegative {
654 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
656 if (target_type == TypeManager.byte_type) {
657 if (in_checked_context){
658 if (Value < Byte.MinValue || Value > Byte.MaxValue)
659 throw new OverflowException ();
661 return new ByteConstant ((byte) Value, Location);
663 if (target_type == TypeManager.sbyte_type) {
664 if (in_checked_context){
665 if (Value < SByte.MinValue || Value > SByte.MaxValue)
666 throw new OverflowException ();
668 return new SByteConstant ((sbyte) Value, Location);
670 if (target_type == TypeManager.ushort_type) {
671 if (in_checked_context && Value < 0)
672 throw new OverflowException ();
674 return new UShortConstant ((ushort) Value, Location);
676 if (target_type == TypeManager.int32_type)
677 return new IntConstant ((int) Value, Location);
678 if (target_type == TypeManager.uint32_type) {
679 if (in_checked_context && Value < 0)
680 throw new OverflowException ();
681 return new UIntConstant ((uint) Value, Location);
683 if (target_type == TypeManager.int64_type)
684 return new LongConstant ((long) Value, Location);
685 if (target_type == TypeManager.uint64_type) {
686 if (in_checked_context && Value < 0)
687 throw new OverflowException ();
688 return new ULongConstant ((ulong) Value, Location);
690 if (target_type == TypeManager.float_type)
691 return new FloatConstant ((float) Value, Location);
692 if (target_type == TypeManager.double_type)
693 return new DoubleConstant ((double) Value, Location);
694 if (target_type == TypeManager.char_type) {
695 if (in_checked_context){
696 if (Value < Char.MinValue)
697 throw new OverflowException ();
699 return new CharConstant ((char) Value, Location);
701 if (target_type == TypeManager.decimal_type)
702 return new DecimalConstant ((decimal) Value, Location);
709 public class UShortConstant : IntegralConstant {
710 public readonly ushort Value;
712 public UShortConstant (ushort v, Location loc):
715 type = TypeManager.ushort_type;
716 eclass = ExprClass.Value;
720 public override void Emit (EmitContext ec)
722 IntLiteral.EmitInt (ec.ig, Value);
725 public override string AsString ()
727 return Value.ToString ();
730 public override object GetValue ()
735 public override Constant Increment ()
737 return new UShortConstant (checked((ushort)(Value + 1)), loc);
740 public override bool IsDefaultValue {
746 public override bool IsNegative {
752 public override bool IsZeroInteger {
753 get { return Value == 0; }
756 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
758 if (target_type == TypeManager.byte_type) {
759 if (in_checked_context){
760 if (Value > Byte.MaxValue)
761 throw new OverflowException ();
763 return new ByteConstant ((byte) Value, Location);
765 if (target_type == TypeManager.sbyte_type) {
766 if (in_checked_context){
767 if (Value > SByte.MaxValue)
768 throw new OverflowException ();
770 return new SByteConstant ((sbyte) Value, Location);
772 if (target_type == TypeManager.short_type) {
773 if (in_checked_context){
774 if (Value > Int16.MaxValue)
775 throw new OverflowException ();
777 return new ShortConstant ((short) Value, Location);
779 if (target_type == TypeManager.int32_type)
780 return new IntConstant ((int) Value, Location);
781 if (target_type == TypeManager.uint32_type)
782 return new UIntConstant ((uint) Value, Location);
783 if (target_type == TypeManager.int64_type)
784 return new LongConstant ((long) Value, Location);
785 if (target_type == TypeManager.uint64_type)
786 return new ULongConstant ((ulong) Value, Location);
787 if (target_type == TypeManager.float_type)
788 return new FloatConstant ((float) Value, Location);
789 if (target_type == TypeManager.double_type)
790 return new DoubleConstant ((double) Value, Location);
791 if (target_type == TypeManager.char_type) {
792 if (in_checked_context){
793 if (Value > Char.MaxValue)
794 throw new OverflowException ();
796 return new CharConstant ((char) Value, Location);
798 if (target_type == TypeManager.decimal_type)
799 return new DecimalConstant ((decimal) Value, Location);
805 public class IntConstant : IntegralConstant {
806 public readonly int Value;
808 public IntConstant (int v, Location loc):
811 type = TypeManager.int32_type;
812 eclass = ExprClass.Value;
816 static public void EmitInt (ILGenerator ig, int i)
820 ig.Emit (OpCodes.Ldc_I4_M1);
824 ig.Emit (OpCodes.Ldc_I4_0);
828 ig.Emit (OpCodes.Ldc_I4_1);
832 ig.Emit (OpCodes.Ldc_I4_2);
836 ig.Emit (OpCodes.Ldc_I4_3);
840 ig.Emit (OpCodes.Ldc_I4_4);
844 ig.Emit (OpCodes.Ldc_I4_5);
848 ig.Emit (OpCodes.Ldc_I4_6);
852 ig.Emit (OpCodes.Ldc_I4_7);
856 ig.Emit (OpCodes.Ldc_I4_8);
860 if (i >= -128 && i <= 127){
861 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
863 ig.Emit (OpCodes.Ldc_I4, i);
868 public override void Emit (EmitContext ec)
870 EmitInt (ec.ig, Value);
873 public override string AsString ()
875 return Value.ToString ();
878 public override object GetValue ()
883 public override Constant Increment ()
885 return new IntConstant (checked(Value + 1), loc);
888 public override bool IsDefaultValue {
894 public override bool IsNegative {
900 public override bool IsZeroInteger {
901 get { return Value == 0; }
904 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
906 if (target_type == TypeManager.byte_type) {
907 if (in_checked_context){
908 if (Value < Byte.MinValue || Value > Byte.MaxValue)
909 throw new OverflowException ();
911 return new ByteConstant ((byte) Value, Location);
913 if (target_type == TypeManager.sbyte_type) {
914 if (in_checked_context){
915 if (Value < SByte.MinValue || Value > SByte.MaxValue)
916 throw new OverflowException ();
918 return new SByteConstant ((sbyte) Value, Location);
920 if (target_type == TypeManager.short_type) {
921 if (in_checked_context){
922 if (Value < Int16.MinValue || Value > Int16.MaxValue)
923 throw new OverflowException ();
925 return new ShortConstant ((short) Value, Location);
927 if (target_type == TypeManager.ushort_type) {
928 if (in_checked_context){
929 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
930 throw new OverflowException ();
932 return new UShortConstant ((ushort) Value, Location);
934 if (target_type == TypeManager.uint32_type) {
935 if (in_checked_context){
936 if (Value < UInt32.MinValue)
937 throw new OverflowException ();
939 return new UIntConstant ((uint) Value, Location);
941 if (target_type == TypeManager.int64_type)
942 return new LongConstant ((long) Value, Location);
943 if (target_type == TypeManager.uint64_type) {
944 if (in_checked_context && Value < 0)
945 throw new OverflowException ();
946 return new ULongConstant ((ulong) Value, Location);
948 if (target_type == TypeManager.float_type)
949 return new FloatConstant ((float) Value, Location);
950 if (target_type == TypeManager.double_type)
951 return new DoubleConstant ((double) Value, Location);
952 if (target_type == TypeManager.char_type) {
953 if (in_checked_context){
954 if (Value < Char.MinValue || Value > Char.MaxValue)
955 throw new OverflowException ();
957 return new CharConstant ((char) Value, Location);
959 if (target_type == TypeManager.decimal_type)
960 return new DecimalConstant ((decimal) Value, Location);
965 public override Constant ConvertImplicitly (Type type)
967 if (this.type == type)
970 Constant c = TryImplicitIntConversion (type);
974 return base.ConvertImplicitly (type);
978 /// Attempts to perform an implicit constant conversion of the IntConstant
979 /// into a different data type using casts (See Implicit Constant
980 /// Expression Conversions)
982 Constant TryImplicitIntConversion (Type target_type)
984 if (target_type == TypeManager.sbyte_type) {
985 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
986 return new SByteConstant ((sbyte) Value, loc);
988 else if (target_type == TypeManager.byte_type) {
989 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
990 return new ByteConstant ((byte) Value, loc);
992 else if (target_type == TypeManager.short_type) {
993 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
994 return new ShortConstant ((short) Value, loc);
996 else if (target_type == TypeManager.ushort_type) {
997 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
998 return new UShortConstant ((ushort) Value, loc);
1000 else if (target_type == TypeManager.uint32_type) {
1002 return new UIntConstant ((uint) Value, loc);
1004 else if (target_type == TypeManager.uint64_type) {
1006 // we can optimize this case: a positive int32
1007 // always fits on a uint64. But we need an opcode
1011 return new ULongConstant ((ulong) Value, loc);
1013 else if (target_type == TypeManager.double_type)
1014 return new DoubleConstant ((double) Value, loc);
1015 else if (target_type == TypeManager.float_type)
1016 return new FloatConstant ((float) Value, loc);
1022 public class UIntConstant : IntegralConstant {
1023 public readonly uint Value;
1025 public UIntConstant (uint v, Location loc):
1028 type = TypeManager.uint32_type;
1029 eclass = ExprClass.Value;
1033 public override void Emit (EmitContext ec)
1035 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1038 public override string AsString ()
1040 return Value.ToString ();
1043 public override object GetValue ()
1048 public override Constant Increment ()
1050 return new UIntConstant (checked(Value + 1), loc);
1053 public override bool IsDefaultValue {
1059 public override bool IsNegative {
1065 public override bool IsZeroInteger {
1066 get { return Value == 0; }
1069 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1071 if (target_type == TypeManager.byte_type) {
1072 if (in_checked_context){
1073 if (Value < Char.MinValue || Value > Char.MaxValue)
1074 throw new OverflowException ();
1076 return new ByteConstant ((byte) Value, Location);
1078 if (target_type == TypeManager.sbyte_type) {
1079 if (in_checked_context){
1080 if (Value > SByte.MaxValue)
1081 throw new OverflowException ();
1083 return new SByteConstant ((sbyte) Value, Location);
1085 if (target_type == TypeManager.short_type) {
1086 if (in_checked_context){
1087 if (Value > Int16.MaxValue)
1088 throw new OverflowException ();
1090 return new ShortConstant ((short) Value, Location);
1092 if (target_type == TypeManager.ushort_type) {
1093 if (in_checked_context){
1094 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1095 throw new OverflowException ();
1097 return new UShortConstant ((ushort) Value, Location);
1099 if (target_type == TypeManager.int32_type) {
1100 if (in_checked_context){
1101 if (Value > Int32.MaxValue)
1102 throw new OverflowException ();
1104 return new IntConstant ((int) Value, Location);
1106 if (target_type == TypeManager.int64_type)
1107 return new LongConstant ((long) Value, Location);
1108 if (target_type == TypeManager.uint64_type)
1109 return new ULongConstant ((ulong) Value, Location);
1110 if (target_type == TypeManager.float_type)
1111 return new FloatConstant ((float) Value, Location);
1112 if (target_type == TypeManager.double_type)
1113 return new DoubleConstant ((double) Value, Location);
1114 if (target_type == TypeManager.char_type) {
1115 if (in_checked_context){
1116 if (Value < Char.MinValue || Value > Char.MaxValue)
1117 throw new OverflowException ();
1119 return new CharConstant ((char) Value, Location);
1121 if (target_type == TypeManager.decimal_type)
1122 return new DecimalConstant ((decimal) Value, Location);
1129 public class LongConstant : IntegralConstant {
1130 public readonly long Value;
1132 public LongConstant (long v, Location loc):
1135 type = TypeManager.int64_type;
1136 eclass = ExprClass.Value;
1140 public override void Emit (EmitContext ec)
1142 EmitLong (ec.ig, Value);
1145 static public void EmitLong (ILGenerator ig, long l)
1147 if (l >= int.MinValue && l <= int.MaxValue) {
1148 IntLiteral.EmitInt (ig, unchecked ((int) l));
1149 ig.Emit (OpCodes.Conv_I8);
1152 ig.Emit (OpCodes.Ldc_I8, l);
1155 public override string AsString ()
1157 return Value.ToString ();
1160 public override object GetValue ()
1165 public override Constant Increment ()
1167 return new LongConstant (checked(Value + 1), loc);
1170 public override bool IsDefaultValue {
1176 public override bool IsNegative {
1182 public override bool IsZeroInteger {
1183 get { return Value == 0; }
1186 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1188 if (target_type == TypeManager.byte_type) {
1189 if (in_checked_context){
1190 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1191 throw new OverflowException ();
1193 return new ByteConstant ((byte) Value, Location);
1195 if (target_type == TypeManager.sbyte_type) {
1196 if (in_checked_context){
1197 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1198 throw new OverflowException ();
1200 return new SByteConstant ((sbyte) Value, Location);
1202 if (target_type == TypeManager.short_type) {
1203 if (in_checked_context){
1204 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1205 throw new OverflowException ();
1207 return new ShortConstant ((short) Value, Location);
1209 if (target_type == TypeManager.ushort_type) {
1210 if (in_checked_context){
1211 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1212 throw new OverflowException ();
1214 return new UShortConstant ((ushort) Value, Location);
1216 if (target_type == TypeManager.int32_type) {
1217 if (in_checked_context){
1218 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1219 throw new OverflowException ();
1221 return new IntConstant ((int) Value, Location);
1223 if (target_type == TypeManager.uint32_type) {
1224 if (in_checked_context){
1225 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1226 throw new OverflowException ();
1228 return new UIntConstant ((uint) Value, Location);
1230 if (target_type == TypeManager.uint64_type) {
1231 if (in_checked_context && Value < 0)
1232 throw new OverflowException ();
1233 return new ULongConstant ((ulong) Value, Location);
1235 if (target_type == TypeManager.float_type)
1236 return new FloatConstant ((float) Value, Location);
1237 if (target_type == TypeManager.double_type)
1238 return new DoubleConstant ((double) Value, Location);
1239 if (target_type == TypeManager.char_type) {
1240 if (in_checked_context){
1241 if (Value < Char.MinValue || Value > Char.MaxValue)
1242 throw new OverflowException ();
1244 return new CharConstant ((char) Value, Location);
1246 if (target_type == TypeManager.decimal_type)
1247 return new DecimalConstant ((decimal) Value, Location);
1252 public override Constant ConvertImplicitly (Type type)
1254 if (Value >= 0 && type == TypeManager.uint64_type) {
1255 return new ULongConstant ((ulong) Value, loc);
1258 return base.ConvertImplicitly (type);
1262 public class ULongConstant : IntegralConstant {
1263 public readonly ulong Value;
1265 public ULongConstant (ulong v, Location loc):
1268 type = TypeManager.uint64_type;
1269 eclass = ExprClass.Value;
1273 public override void Emit (EmitContext ec)
1275 ILGenerator ig = ec.ig;
1277 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1280 public override string AsString ()
1282 return Value.ToString ();
1285 public override object GetValue ()
1290 public override Constant Increment ()
1292 return new ULongConstant (checked(Value + 1), loc);
1295 public override bool IsDefaultValue {
1301 public override bool IsNegative {
1307 public override bool IsZeroInteger {
1308 get { return Value == 0; }
1311 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1313 if (target_type == TypeManager.byte_type) {
1314 if (in_checked_context && Value > Byte.MaxValue)
1315 throw new OverflowException ();
1316 return new ByteConstant ((byte) Value, Location);
1318 if (target_type == TypeManager.sbyte_type) {
1319 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1320 throw new OverflowException ();
1321 return new SByteConstant ((sbyte) Value, Location);
1323 if (target_type == TypeManager.short_type) {
1324 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1325 throw new OverflowException ();
1326 return new ShortConstant ((short) Value, Location);
1328 if (target_type == TypeManager.ushort_type) {
1329 if (in_checked_context && Value > UInt16.MaxValue)
1330 throw new OverflowException ();
1331 return new UShortConstant ((ushort) Value, Location);
1333 if (target_type == TypeManager.int32_type) {
1334 if (in_checked_context && Value > UInt32.MaxValue)
1335 throw new OverflowException ();
1336 return new IntConstant ((int) Value, Location);
1338 if (target_type == TypeManager.uint32_type) {
1339 if (in_checked_context && Value > UInt32.MaxValue)
1340 throw new OverflowException ();
1341 return new UIntConstant ((uint) Value, Location);
1343 if (target_type == TypeManager.int64_type) {
1344 if (in_checked_context && Value > Int64.MaxValue)
1345 throw new OverflowException ();
1346 return new LongConstant ((long) Value, Location);
1348 if (target_type == TypeManager.float_type)
1349 return new FloatConstant ((float) Value, Location);
1350 if (target_type == TypeManager.double_type)
1351 return new DoubleConstant ((double) Value, Location);
1352 if (target_type == TypeManager.char_type) {
1353 if (in_checked_context && Value > Char.MaxValue)
1354 throw new OverflowException ();
1355 return new CharConstant ((char) Value, Location);
1357 if (target_type == TypeManager.decimal_type)
1358 return new DecimalConstant ((decimal) Value, Location);
1365 public class FloatConstant : Constant {
1368 public FloatConstant (float v, Location loc):
1371 type = TypeManager.float_type;
1372 eclass = ExprClass.Value;
1376 public override void Emit (EmitContext ec)
1378 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1381 public override string AsString ()
1383 return Value.ToString ();
1386 public override object GetValue ()
1391 public override Constant Increment ()
1393 return new FloatConstant (checked(Value + 1), loc);
1396 public override bool IsDefaultValue {
1402 public override bool IsNegative {
1408 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1410 if (target_type == TypeManager.byte_type) {
1411 if (in_checked_context){
1412 if (Value < byte.MinValue || Value > byte.MaxValue)
1413 throw new OverflowException ();
1415 return new ByteConstant ((byte) Value, Location);
1417 if (target_type == TypeManager.sbyte_type) {
1418 if (in_checked_context){
1419 if (Value < sbyte.MinValue || Value > sbyte.MaxValue)
1420 throw new OverflowException ();
1422 return new SByteConstant ((sbyte) Value, Location);
1424 if (target_type == TypeManager.short_type) {
1425 if (in_checked_context){
1426 if (Value < short.MinValue || Value > short.MaxValue)
1427 throw new OverflowException ();
1429 return new ShortConstant ((short) Value, Location);
1431 if (target_type == TypeManager.ushort_type) {
1432 if (in_checked_context){
1433 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1434 throw new OverflowException ();
1436 return new UShortConstant ((ushort) Value, Location);
1438 if (target_type == TypeManager.int32_type) {
1439 if (in_checked_context){
1440 if (Value < int.MinValue || Value > int.MaxValue)
1441 throw new OverflowException ();
1443 return new IntConstant ((int) Value, Location);
1445 if (target_type == TypeManager.uint32_type) {
1446 if (in_checked_context){
1447 if (Value < uint.MinValue || Value > uint.MaxValue)
1448 throw new OverflowException ();
1450 return new UIntConstant ((uint) Value, Location);
1452 if (target_type == TypeManager.int64_type) {
1453 if (in_checked_context){
1454 if (Value < long.MinValue || Value > long.MaxValue)
1455 throw new OverflowException ();
1457 return new LongConstant ((long) Value, Location);
1459 if (target_type == TypeManager.uint64_type) {
1460 if (in_checked_context){
1461 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1462 throw new OverflowException ();
1464 return new ULongConstant ((ulong) Value, Location);
1466 if (target_type == TypeManager.double_type)
1467 return new DoubleConstant ((double) Value, Location);
1468 if (target_type == TypeManager.char_type) {
1469 if (in_checked_context){
1470 if (Value < (float) char.MinValue || Value > (float) char.MaxValue)
1471 throw new OverflowException ();
1473 return new CharConstant ((char) Value, Location);
1475 if (target_type == TypeManager.decimal_type)
1476 return new DecimalConstant ((decimal) Value, Location);
1483 public class DoubleConstant : Constant {
1484 public double Value;
1486 public DoubleConstant (double v, Location loc):
1489 type = TypeManager.double_type;
1490 eclass = ExprClass.Value;
1494 public override void Emit (EmitContext ec)
1496 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1499 public override string AsString ()
1501 return Value.ToString ();
1504 public override object GetValue ()
1509 public override Constant Increment ()
1511 return new DoubleConstant (checked(Value + 1), loc);
1514 public override bool IsDefaultValue {
1520 public override bool IsNegative {
1526 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1528 if (target_type == TypeManager.byte_type) {
1529 if (in_checked_context){
1530 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1531 throw new OverflowException ();
1533 return new ByteConstant ((byte) Value, Location);
1535 if (target_type == TypeManager.sbyte_type) {
1536 if (in_checked_context){
1537 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1538 throw new OverflowException ();
1540 return new SByteConstant ((sbyte) Value, Location);
1542 if (target_type == TypeManager.short_type) {
1543 if (in_checked_context){
1544 if (Value < short.MinValue || Value > short.MaxValue)
1545 throw new OverflowException ();
1547 return new ShortConstant ((short) Value, Location);
1549 if (target_type == TypeManager.ushort_type) {
1550 if (in_checked_context){
1551 if (Value < ushort.MinValue || Value > ushort.MaxValue)
1552 throw new OverflowException ();
1554 return new UShortConstant ((ushort) Value, Location);
1556 if (target_type == TypeManager.int32_type) {
1557 if (in_checked_context){
1558 if (Value < int.MinValue || Value > int.MaxValue)
1559 throw new OverflowException ();
1561 return new IntConstant ((int) Value, Location);
1563 if (target_type == TypeManager.uint32_type) {
1564 if (in_checked_context){
1565 if (Value < uint.MinValue || Value > uint.MaxValue)
1566 throw new OverflowException ();
1568 return new UIntConstant ((uint) Value, Location);
1570 if (target_type == TypeManager.int64_type) {
1571 if (in_checked_context){
1572 if (Value < long.MinValue || Value > long.MaxValue)
1573 throw new OverflowException ();
1575 return new LongConstant ((long) Value, Location);
1577 if (target_type == TypeManager.uint64_type) {
1578 if (in_checked_context){
1579 if (Value < ulong.MinValue || Value > ulong.MaxValue)
1580 throw new OverflowException ();
1582 return new ULongConstant ((ulong) Value, Location);
1584 if (target_type == TypeManager.float_type)
1585 return new FloatConstant ((float) Value, Location);
1586 if (target_type == TypeManager.char_type) {
1587 if (in_checked_context){
1588 if (Value < (double) char.MinValue || Value > (double) char.MaxValue)
1589 throw new OverflowException ();
1591 return new CharConstant ((char) Value, Location);
1593 if (target_type == TypeManager.decimal_type)
1594 return new DecimalConstant ((decimal) Value, Location);
1601 public class DecimalConstant : Constant {
1602 public readonly decimal Value;
1604 public DecimalConstant (decimal d, Location loc):
1607 type = TypeManager.decimal_type;
1608 eclass = ExprClass.Value;
1612 override public string AsString ()
1614 return Value.ToString ();
1617 public override object GetValue ()
1619 return (object) Value;
1622 public override void Emit (EmitContext ec)
1624 ILGenerator ig = ec.ig;
1626 int [] words = Decimal.GetBits (Value);
1627 int power = (words [3] >> 16) & 0xff;
1629 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1631 if (TypeManager.void_decimal_ctor_int_arg == null) {
1632 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1633 TypeManager.decimal_type, loc, TypeManager.int32_type);
1635 if (TypeManager.void_decimal_ctor_int_arg == null)
1639 IntConstant.EmitInt (ig, (int)Value);
1640 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1646 // FIXME: we could optimize this, and call a better
1650 IntConstant.EmitInt (ig, words [0]);
1651 IntConstant.EmitInt (ig, words [1]);
1652 IntConstant.EmitInt (ig, words [2]);
1655 IntConstant.EmitInt (ig, words [3] >> 31);
1658 IntConstant.EmitInt (ig, power);
1660 if (TypeManager.void_decimal_ctor_five_args == null) {
1661 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1662 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1663 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1665 if (TypeManager.void_decimal_ctor_five_args == null)
1669 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1672 public override Constant Increment ()
1674 return new DecimalConstant (checked (Value + 1), loc);
1677 public override bool IsDefaultValue {
1683 public override bool IsNegative {
1689 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1691 if (target_type == TypeManager.sbyte_type)
1692 return new SByteConstant ((sbyte)Value, loc);
1693 if (target_type == TypeManager.byte_type)
1694 return new ByteConstant ((byte)Value, loc);
1695 if (target_type == TypeManager.short_type)
1696 return new ShortConstant ((short)Value, loc);
1697 if (target_type == TypeManager.ushort_type)
1698 return new UShortConstant ((ushort)Value, loc);
1699 if (target_type == TypeManager.int32_type)
1700 return new IntConstant ((int)Value, loc);
1701 if (target_type == TypeManager.uint32_type)
1702 return new UIntConstant ((uint)Value, loc);
1703 if (target_type == TypeManager.int64_type)
1704 return new LongConstant ((long)Value, loc);
1705 if (target_type == TypeManager.uint64_type)
1706 return new ULongConstant ((ulong)Value, loc);
1707 if (target_type == TypeManager.char_type)
1708 return new CharConstant ((char)Value, loc);
1709 if (target_type == TypeManager.float_type)
1710 return new FloatConstant ((float)Value, loc);
1711 if (target_type == TypeManager.double_type)
1712 return new DoubleConstant ((double)Value, loc);
1719 public class StringConstant : Constant {
1720 public readonly string Value;
1722 public StringConstant (string s, Location loc):
1725 type = TypeManager.string_type;
1726 eclass = ExprClass.Value;
1730 // FIXME: Escape the string.
1731 override public string AsString ()
1733 return "\"" + Value + "\"";
1736 public override object GetValue ()
1741 public override void Emit (EmitContext ec)
1744 ec.ig.Emit (OpCodes.Ldnull);
1746 ec.ig.Emit (OpCodes.Ldstr, Value);
1749 public override Constant Increment ()
1751 throw new NotSupportedException ();
1754 public override bool IsDefaultValue {
1756 return Value == null;
1760 public override bool IsNegative {
1766 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1773 /// The value is constant, but when emitted has a side effect. This is
1774 /// used by BitwiseAnd to ensure that the second expression is invoked
1775 /// regardless of the value of the left side.
1778 public class SideEffectConstant : Constant {
1779 public Constant left;
1782 public SideEffectConstant (Constant left, Expression right, Location loc) : base (loc)
1786 eclass = ExprClass.Value;
1790 public override string AsString ()
1792 return left.AsString ();
1795 public override object GetValue ()
1797 return left.GetValue ();
1800 public override void Emit (EmitContext ec)
1803 // This happens when both sides have side-effects and
1804 // the result is a constant
1806 if (left is SideEffectConstant) {
1808 ec.ig.Emit (OpCodes.Pop);
1814 public override bool IsDefaultValue {
1816 return left.IsDefaultValue;
1820 public override Constant Increment ()
1822 throw new NotSupportedException ();
1825 public override bool IsNegative {
1827 return left.IsNegative;
1831 public override bool IsZeroInteger {
1833 return left.IsZeroInteger;
1837 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1839 return left.ConvertExplicitly (in_checked_context, target_type);