2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
15 using IKVM.Reflection.Emit;
17 using System.Reflection.Emit;
20 namespace Mono.CSharp {
23 /// Base class for constants and literals.
25 public abstract class Constant : Expression {
27 protected Constant (Location loc)
32 override public string ToString ()
34 return this.GetType ().Name + " (" + GetValueAsLiteral () + ")";
38 /// This is used to obtain the actual value of the literal
39 /// cast into an object.
41 public abstract object GetValue ();
43 public abstract string GetValueAsLiteral ();
47 // Returns an object value which is typed to contant type
49 public virtual object GetTypedValue ()
55 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
57 if (!expl && IsLiteral &&
58 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
59 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
60 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
61 GetValueAsLiteral (), TypeManager.CSharpName (target));
63 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
67 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
69 Constant c = ConvertImplicitly (ec, type);
71 Error_ValueCannotBeConverted (ec, loc, type, false);
76 public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
78 if (this.type == type)
81 if (Convert.ImplicitNumericConversion (this, type) == null)
85 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
88 // We should always catch the error before this is ever
89 // reached, by calling Convert.ImplicitStandardConversionExists
91 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
92 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
95 return CreateConstant (rc, type, constant_value, loc);
99 // Returns a constant instance based on Type
101 public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc)
103 return CreateConstantFromValue (t, v, loc).Resolve (rc);
106 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
108 if (t == TypeManager.int32_type)
109 return new IntConstant ((int) v, loc);
110 if (t == TypeManager.string_type)
111 return new StringConstant ((string) v, loc);
112 if (t == TypeManager.uint32_type)
113 return new UIntConstant ((uint) v, loc);
114 if (t == TypeManager.int64_type)
115 return new LongConstant ((long) v, loc);
116 if (t == TypeManager.uint64_type)
117 return new ULongConstant ((ulong) v, loc);
118 if (t == TypeManager.float_type)
119 return new FloatConstant ((float) v, loc);
120 if (t == TypeManager.double_type)
121 return new DoubleConstant ((double) v, loc);
122 if (t == TypeManager.short_type)
123 return new ShortConstant ((short)v, loc);
124 if (t == TypeManager.ushort_type)
125 return new UShortConstant ((ushort)v, loc);
126 if (t == TypeManager.sbyte_type)
127 return new SByteConstant ((sbyte)v, loc);
128 if (t == TypeManager.byte_type)
129 return new ByteConstant ((byte)v, loc);
130 if (t == TypeManager.char_type)
131 return new CharConstant ((char)v, loc);
132 if (t == TypeManager.bool_type)
133 return new BoolConstant ((bool) v, loc);
134 if (t == TypeManager.decimal_type)
135 return new DecimalConstant ((decimal) v, loc);
136 if (TypeManager.IsEnumType (t)) {
137 var real_type = EnumSpec.GetUnderlyingType (t);
138 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
141 if (TypeManager.IsNullableType (t))
142 return Nullable.LiftedNull.Create (t, loc);
144 if (TypeManager.IsReferenceType (t))
145 return new NullConstant (t, loc);
148 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
149 v, TypeManager.CSharpName (t));
152 public override Expression CreateExpressionTree (ResolveContext ec)
154 Arguments args = new Arguments (2);
155 args.Add (new Argument (this));
156 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
158 return CreateExpressionFactoryCall (ec, "Constant", args);
163 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
164 /// It throws OverflowException
166 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
167 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
170 /// Attempts to do a compile-time folding of a constant cast.
172 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
175 return TryReduce (ec, target_type);
177 catch (OverflowException) {
178 if (ec.ConstantCheckState && Type.BuildinType != BuildinTypeSpec.Type.Decimal) {
179 ec.Report.Error (221, loc,
180 "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
181 GetValueAsLiteral (), target_type.GetSignatureForError ());
183 Error_ValueCannotBeConverted (ec, loc, target_type, false);
186 return New.Constantify (target_type, loc).Resolve (ec);
190 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
192 if (Type == target_type)
196 if (TypeManager.IsEnumType (target_type)) {
197 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
201 return new EnumConstant (c, target_type).Resolve (ec);
204 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
212 /// Need to pass type as the constant can require a boxing
213 /// and in such case no optimization is possible
215 public bool IsDefaultInitializer (TypeSpec type)
218 return IsDefaultValue;
220 return this is NullLiteral;
223 public abstract bool IsDefaultValue {
227 public abstract bool IsNegative {
232 // When constant is declared as literal
234 public virtual bool IsLiteral {
235 get { return false; }
238 public virtual bool IsOneInteger {
239 get { return false; }
243 // Returns true iff 1) the stack type of this is one of Object,
244 // int32, int64 and 2) this == 0 or this == null.
246 public virtual bool IsZeroInteger {
247 get { return false; }
250 public override void EmitSideEffect (EmitContext ec)
255 public sealed override Expression Clone (CloneContext clonectx)
257 // No cloning is not needed for constants
261 protected override void CloneTo (CloneContext clonectx, Expression target)
263 throw new NotSupportedException ("should not be reached");
266 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
269 return base.MakeExpression (ctx);
271 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
275 public new Constant Resolve (ResolveContext rc)
277 if (eclass != ExprClass.Unresolved)
280 // Resolved constant has to be still a constant
281 Constant c = (Constant) DoResolve (rc);
285 if ((c.eclass & ExprClass.Value) == 0) {
286 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
291 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
297 public abstract class IntegralConstant : Constant
299 protected IntegralConstant (Location loc) :
304 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
307 ConvertExplicitly (true, target);
308 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
312 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
313 GetValue ().ToString (), TypeManager.CSharpName (target));
317 public override string GetValueAsLiteral ()
319 return GetValue ().ToString ();
322 public abstract Constant Increment ();
325 public class BoolConstant : Constant {
326 public readonly bool Value;
328 public BoolConstant (bool val, Location loc):
334 protected override Expression DoResolve (ResolveContext ec)
336 type = TypeManager.bool_type;
337 eclass = ExprClass.Value;
341 public override object GetValue ()
343 return (object) Value;
346 public override string GetValueAsLiteral ()
348 return Value ? "true" : "false";
351 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
356 public override void Emit (EmitContext ec)
359 ec.Emit (OpCodes.Ldc_I4_1);
361 ec.Emit (OpCodes.Ldc_I4_0);
364 public override bool IsDefaultValue {
370 public override bool IsNegative {
376 public override bool IsZeroInteger {
377 get { return Value == false; }
380 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
387 public class ByteConstant : IntegralConstant {
388 public readonly byte Value;
390 public ByteConstant (byte v, Location loc):
396 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
401 public override void Emit (EmitContext ec)
406 protected override Expression DoResolve (ResolveContext ec)
408 type = TypeManager.byte_type;
409 eclass = ExprClass.Value;
413 public override object GetValue ()
418 public override Constant Increment ()
420 return new ByteConstant (checked ((byte)(Value + 1)), loc);
423 public override bool IsDefaultValue {
429 public override bool IsOneInteger {
435 public override bool IsNegative {
441 public override bool IsZeroInteger {
442 get { return Value == 0; }
445 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
447 if (target_type == TypeManager.sbyte_type) {
448 if (in_checked_context){
449 if (Value > SByte.MaxValue)
450 throw new OverflowException ();
452 return new SByteConstant ((sbyte) Value, Location);
454 if (target_type == TypeManager.short_type)
455 return new ShortConstant ((short) Value, Location);
456 if (target_type == TypeManager.ushort_type)
457 return new UShortConstant ((ushort) Value, Location);
458 if (target_type == TypeManager.int32_type)
459 return new IntConstant ((int) Value, Location);
460 if (target_type == TypeManager.uint32_type)
461 return new UIntConstant ((uint) Value, Location);
462 if (target_type == TypeManager.int64_type)
463 return new LongConstant ((long) Value, Location);
464 if (target_type == TypeManager.uint64_type)
465 return new ULongConstant ((ulong) Value, Location);
466 if (target_type == TypeManager.float_type)
467 return new FloatConstant ((float) Value, Location);
468 if (target_type == TypeManager.double_type)
469 return new DoubleConstant ((double) Value, Location);
470 if (target_type == TypeManager.char_type)
471 return new CharConstant ((char) Value, Location);
472 if (target_type == TypeManager.decimal_type)
473 return new DecimalConstant ((decimal) Value, Location);
480 public class CharConstant : Constant {
481 public readonly char Value;
483 public CharConstant (char v, Location loc):
489 protected override Expression DoResolve (ResolveContext rc)
491 type = TypeManager.char_type;
492 eclass = ExprClass.Value;
496 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
498 enc.Encode ((ushort) Value);
501 public override void Emit (EmitContext ec)
506 static string descape (char c)
532 return c.ToString ();
535 public override object GetValue ()
540 public override string GetValueAsLiteral ()
542 return "\"" + descape (Value) + "\"";
545 public override bool IsDefaultValue {
551 public override bool IsNegative {
557 public override bool IsZeroInteger {
558 get { return Value == '\0'; }
561 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
563 if (target_type == TypeManager.byte_type) {
564 if (in_checked_context){
565 if (Value < Byte.MinValue || Value > Byte.MaxValue)
566 throw new OverflowException ();
568 return new ByteConstant ((byte) Value, Location);
570 if (target_type == TypeManager.sbyte_type) {
571 if (in_checked_context){
572 if (Value > SByte.MaxValue)
573 throw new OverflowException ();
575 return new SByteConstant ((sbyte) Value, Location);
577 if (target_type == TypeManager.short_type) {
578 if (in_checked_context){
579 if (Value > Int16.MaxValue)
580 throw new OverflowException ();
582 return new ShortConstant ((short) Value, Location);
584 if (target_type == TypeManager.int32_type)
585 return new IntConstant ((int) Value, Location);
586 if (target_type == TypeManager.uint32_type)
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 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.decimal_type)
597 return new DecimalConstant ((decimal) Value, Location);
604 public class SByteConstant : IntegralConstant {
605 public readonly sbyte Value;
607 public SByteConstant (sbyte v, Location loc):
613 protected override Expression DoResolve (ResolveContext rc)
615 type = TypeManager.sbyte_type;
616 eclass = ExprClass.Value;
620 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
625 public override void Emit (EmitContext ec)
630 public override object GetValue ()
635 public override Constant Increment ()
637 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
640 public override bool IsDefaultValue {
646 public override bool IsNegative {
652 public override bool IsOneInteger {
658 public override bool IsZeroInteger {
659 get { return Value == 0; }
662 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
664 if (target_type == TypeManager.byte_type) {
665 if (in_checked_context && Value < 0)
666 throw new OverflowException ();
667 return new ByteConstant ((byte) Value, Location);
669 if (target_type == TypeManager.short_type)
670 return new ShortConstant ((short) Value, Location);
671 if (target_type == TypeManager.ushort_type) {
672 if (in_checked_context && Value < 0)
673 throw new OverflowException ();
674 return new UShortConstant ((ushort) Value, Location);
675 } if (target_type == TypeManager.int32_type)
676 return new IntConstant ((int) Value, Location);
677 if (target_type == TypeManager.uint32_type) {
678 if (in_checked_context && Value < 0)
679 throw new OverflowException ();
680 return new UIntConstant ((uint) Value, Location);
681 } if (target_type == TypeManager.int64_type)
682 return new LongConstant ((long) Value, Location);
683 if (target_type == TypeManager.uint64_type) {
684 if (in_checked_context && Value < 0)
685 throw new OverflowException ();
686 return new ULongConstant ((ulong) Value, Location);
688 if (target_type == TypeManager.float_type)
689 return new FloatConstant ((float) Value, Location);
690 if (target_type == TypeManager.double_type)
691 return new DoubleConstant ((double) Value, Location);
692 if (target_type == TypeManager.char_type) {
693 if (in_checked_context && Value < 0)
694 throw new OverflowException ();
695 return new CharConstant ((char) Value, Location);
697 if (target_type == TypeManager.decimal_type)
698 return new DecimalConstant ((decimal) Value, Location);
705 public class ShortConstant : IntegralConstant {
706 public readonly short Value;
708 public ShortConstant (short v, Location loc):
714 protected override Expression DoResolve (ResolveContext rc)
716 type = TypeManager.short_type;
717 eclass = ExprClass.Value;
721 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
726 public override void Emit (EmitContext ec)
731 public override object GetValue ()
736 public override Constant Increment ()
738 return new ShortConstant (checked((short)(Value + 1)), loc);
741 public override bool IsDefaultValue {
747 public override bool IsZeroInteger {
748 get { return Value == 0; }
751 public override bool IsNegative {
757 public override bool IsOneInteger {
763 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
765 if (target_type == TypeManager.byte_type) {
766 if (in_checked_context){
767 if (Value < Byte.MinValue || Value > Byte.MaxValue)
768 throw new OverflowException ();
770 return new ByteConstant ((byte) Value, Location);
772 if (target_type == TypeManager.sbyte_type) {
773 if (in_checked_context){
774 if (Value < SByte.MinValue || Value > SByte.MaxValue)
775 throw new OverflowException ();
777 return new SByteConstant ((sbyte) Value, Location);
779 if (target_type == TypeManager.ushort_type) {
780 if (in_checked_context && Value < 0)
781 throw new OverflowException ();
783 return new UShortConstant ((ushort) Value, Location);
785 if (target_type == TypeManager.int32_type)
786 return new IntConstant ((int) Value, Location);
787 if (target_type == TypeManager.uint32_type) {
788 if (in_checked_context && Value < 0)
789 throw new OverflowException ();
790 return new UIntConstant ((uint) Value, Location);
792 if (target_type == TypeManager.int64_type)
793 return new LongConstant ((long) Value, Location);
794 if (target_type == TypeManager.uint64_type) {
795 if (in_checked_context && Value < 0)
796 throw new OverflowException ();
797 return new ULongConstant ((ulong) Value, Location);
799 if (target_type == TypeManager.float_type)
800 return new FloatConstant ((float) Value, Location);
801 if (target_type == TypeManager.double_type)
802 return new DoubleConstant ((double) Value, Location);
803 if (target_type == TypeManager.char_type) {
804 if (in_checked_context){
805 if (Value < Char.MinValue)
806 throw new OverflowException ();
808 return new CharConstant ((char) Value, Location);
810 if (target_type == TypeManager.decimal_type)
811 return new DecimalConstant ((decimal) Value, Location);
818 public class UShortConstant : IntegralConstant {
819 public readonly ushort Value;
821 public UShortConstant (ushort v, Location loc):
827 protected override Expression DoResolve (ResolveContext rc)
829 type = TypeManager.ushort_type;
830 eclass = ExprClass.Value;
834 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
839 public override void Emit (EmitContext ec)
844 public override object GetValue ()
849 public override Constant Increment ()
851 return new UShortConstant (checked((ushort)(Value + 1)), loc);
854 public override bool IsDefaultValue {
860 public override bool IsNegative {
866 public override bool IsOneInteger {
872 public override bool IsZeroInteger {
873 get { return Value == 0; }
876 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
878 if (target_type == TypeManager.byte_type) {
879 if (in_checked_context){
880 if (Value > Byte.MaxValue)
881 throw new OverflowException ();
883 return new ByteConstant ((byte) Value, Location);
885 if (target_type == TypeManager.sbyte_type) {
886 if (in_checked_context){
887 if (Value > SByte.MaxValue)
888 throw new OverflowException ();
890 return new SByteConstant ((sbyte) Value, Location);
892 if (target_type == TypeManager.short_type) {
893 if (in_checked_context){
894 if (Value > Int16.MaxValue)
895 throw new OverflowException ();
897 return new ShortConstant ((short) Value, Location);
899 if (target_type == TypeManager.int32_type)
900 return new IntConstant ((int) Value, Location);
901 if (target_type == TypeManager.uint32_type)
902 return new UIntConstant ((uint) Value, Location);
903 if (target_type == TypeManager.int64_type)
904 return new LongConstant ((long) Value, Location);
905 if (target_type == TypeManager.uint64_type)
906 return new ULongConstant ((ulong) Value, Location);
907 if (target_type == TypeManager.float_type)
908 return new FloatConstant ((float) Value, Location);
909 if (target_type == TypeManager.double_type)
910 return new DoubleConstant ((double) Value, Location);
911 if (target_type == TypeManager.char_type) {
912 if (in_checked_context){
913 if (Value > Char.MaxValue)
914 throw new OverflowException ();
916 return new CharConstant ((char) Value, Location);
918 if (target_type == TypeManager.decimal_type)
919 return new DecimalConstant ((decimal) Value, Location);
925 public class IntConstant : IntegralConstant {
926 public readonly int Value;
928 public IntConstant (int v, Location loc):
934 protected override Expression DoResolve (ResolveContext rc)
936 type = TypeManager.int32_type;
937 eclass = ExprClass.Value;
941 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
946 public override void Emit (EmitContext ec)
951 public override object GetValue ()
956 public override Constant Increment ()
958 return new IntConstant (checked(Value + 1), loc);
961 public override bool IsDefaultValue {
967 public override bool IsNegative {
973 public override bool IsOneInteger {
979 public override bool IsZeroInteger {
980 get { return Value == 0; }
983 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
985 if (target_type == TypeManager.byte_type) {
986 if (in_checked_context){
987 if (Value < Byte.MinValue || Value > Byte.MaxValue)
988 throw new OverflowException ();
990 return new ByteConstant ((byte) Value, Location);
992 if (target_type == TypeManager.sbyte_type) {
993 if (in_checked_context){
994 if (Value < SByte.MinValue || Value > SByte.MaxValue)
995 throw new OverflowException ();
997 return new SByteConstant ((sbyte) Value, Location);
999 if (target_type == TypeManager.short_type) {
1000 if (in_checked_context){
1001 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1002 throw new OverflowException ();
1004 return new ShortConstant ((short) Value, Location);
1006 if (target_type == TypeManager.ushort_type) {
1007 if (in_checked_context){
1008 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1009 throw new OverflowException ();
1011 return new UShortConstant ((ushort) Value, Location);
1013 if (target_type == TypeManager.uint32_type) {
1014 if (in_checked_context){
1015 if (Value < UInt32.MinValue)
1016 throw new OverflowException ();
1018 return new UIntConstant ((uint) Value, Location);
1020 if (target_type == TypeManager.int64_type)
1021 return new LongConstant ((long) Value, Location);
1022 if (target_type == TypeManager.uint64_type) {
1023 if (in_checked_context && Value < 0)
1024 throw new OverflowException ();
1025 return new ULongConstant ((ulong) Value, Location);
1027 if (target_type == TypeManager.float_type)
1028 return new FloatConstant ((float) Value, Location);
1029 if (target_type == TypeManager.double_type)
1030 return new DoubleConstant ((double) Value, Location);
1031 if (target_type == TypeManager.char_type) {
1032 if (in_checked_context){
1033 if (Value < Char.MinValue || Value > Char.MaxValue)
1034 throw new OverflowException ();
1036 return new CharConstant ((char) Value, Location);
1038 if (target_type == TypeManager.decimal_type)
1039 return new DecimalConstant ((decimal) Value, Location);
1044 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1046 if (this.type == type)
1049 Constant c = TryImplicitIntConversion (type);
1051 return c.Resolve (rc);
1053 return base.ConvertImplicitly (rc, type);
1057 /// Attempts to perform an implicit constant conversion of the IntConstant
1058 /// into a different data type using casts (See Implicit Constant
1059 /// Expression Conversions)
1061 Constant TryImplicitIntConversion (TypeSpec target_type)
1063 if (target_type == TypeManager.sbyte_type) {
1064 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1065 return new SByteConstant ((sbyte) Value, loc);
1067 else if (target_type == TypeManager.byte_type) {
1068 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1069 return new ByteConstant ((byte) Value, loc);
1071 else if (target_type == TypeManager.short_type) {
1072 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1073 return new ShortConstant ((short) Value, loc);
1075 else if (target_type == TypeManager.ushort_type) {
1076 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1077 return new UShortConstant ((ushort) Value, loc);
1079 else if (target_type == TypeManager.uint32_type) {
1081 return new UIntConstant ((uint) Value, loc);
1083 else if (target_type == TypeManager.uint64_type) {
1085 // we can optimize this case: a positive int32
1086 // always fits on a uint64. But we need an opcode
1090 return new ULongConstant ((ulong) Value, loc);
1092 else if (target_type == TypeManager.double_type)
1093 return new DoubleConstant ((double) Value, loc);
1094 else if (target_type == TypeManager.float_type)
1095 return new FloatConstant ((float) Value, loc);
1101 public class UIntConstant : IntegralConstant {
1102 public readonly uint Value;
1104 public UIntConstant (uint v, Location loc):
1110 protected override Expression DoResolve (ResolveContext rc)
1112 type = TypeManager.uint32_type;
1113 eclass = ExprClass.Value;
1117 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1122 public override void Emit (EmitContext ec)
1124 ec.EmitInt (unchecked ((int) Value));
1127 public override object GetValue ()
1132 public override Constant Increment ()
1134 return new UIntConstant (checked(Value + 1), loc);
1137 public override bool IsDefaultValue {
1143 public override bool IsNegative {
1149 public override bool IsOneInteger {
1155 public override bool IsZeroInteger {
1156 get { return Value == 0; }
1159 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1161 if (target_type == TypeManager.byte_type) {
1162 if (in_checked_context){
1163 if (Value < 0 || Value > byte.MaxValue)
1164 throw new OverflowException ();
1166 return new ByteConstant ((byte) Value, Location);
1168 if (target_type == TypeManager.sbyte_type) {
1169 if (in_checked_context){
1170 if (Value > SByte.MaxValue)
1171 throw new OverflowException ();
1173 return new SByteConstant ((sbyte) Value, Location);
1175 if (target_type == TypeManager.short_type) {
1176 if (in_checked_context){
1177 if (Value > Int16.MaxValue)
1178 throw new OverflowException ();
1180 return new ShortConstant ((short) Value, Location);
1182 if (target_type == TypeManager.ushort_type) {
1183 if (in_checked_context){
1184 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1185 throw new OverflowException ();
1187 return new UShortConstant ((ushort) Value, Location);
1189 if (target_type == TypeManager.int32_type) {
1190 if (in_checked_context){
1191 if (Value > Int32.MaxValue)
1192 throw new OverflowException ();
1194 return new IntConstant ((int) Value, Location);
1196 if (target_type == TypeManager.int64_type)
1197 return new LongConstant ((long) Value, Location);
1198 if (target_type == TypeManager.uint64_type)
1199 return new ULongConstant ((ulong) Value, Location);
1200 if (target_type == TypeManager.float_type)
1201 return new FloatConstant ((float) Value, Location);
1202 if (target_type == TypeManager.double_type)
1203 return new DoubleConstant ((double) Value, Location);
1204 if (target_type == TypeManager.char_type) {
1205 if (in_checked_context){
1206 if (Value < Char.MinValue || Value > Char.MaxValue)
1207 throw new OverflowException ();
1209 return new CharConstant ((char) Value, Location);
1211 if (target_type == TypeManager.decimal_type)
1212 return new DecimalConstant ((decimal) Value, Location);
1219 public class LongConstant : IntegralConstant {
1220 public readonly long Value;
1222 public LongConstant (long v, Location loc):
1228 protected override Expression DoResolve (ResolveContext rc)
1230 type = TypeManager.int64_type;
1231 eclass = ExprClass.Value;
1235 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1240 public override void Emit (EmitContext ec)
1242 ec.EmitLong (Value);
1245 public override object GetValue ()
1250 public override Constant Increment ()
1252 return new LongConstant (checked(Value + 1), loc);
1255 public override bool IsDefaultValue {
1261 public override bool IsNegative {
1267 public override bool IsOneInteger {
1273 public override bool IsZeroInteger {
1274 get { return Value == 0; }
1277 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1279 if (target_type == TypeManager.byte_type) {
1280 if (in_checked_context){
1281 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1282 throw new OverflowException ();
1284 return new ByteConstant ((byte) Value, Location);
1286 if (target_type == TypeManager.sbyte_type) {
1287 if (in_checked_context){
1288 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1289 throw new OverflowException ();
1291 return new SByteConstant ((sbyte) Value, Location);
1293 if (target_type == TypeManager.short_type) {
1294 if (in_checked_context){
1295 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1296 throw new OverflowException ();
1298 return new ShortConstant ((short) Value, Location);
1300 if (target_type == TypeManager.ushort_type) {
1301 if (in_checked_context){
1302 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1303 throw new OverflowException ();
1305 return new UShortConstant ((ushort) Value, Location);
1307 if (target_type == TypeManager.int32_type) {
1308 if (in_checked_context){
1309 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1310 throw new OverflowException ();
1312 return new IntConstant ((int) Value, Location);
1314 if (target_type == TypeManager.uint32_type) {
1315 if (in_checked_context){
1316 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1317 throw new OverflowException ();
1319 return new UIntConstant ((uint) Value, Location);
1321 if (target_type == TypeManager.uint64_type) {
1322 if (in_checked_context && Value < 0)
1323 throw new OverflowException ();
1324 return new ULongConstant ((ulong) Value, Location);
1326 if (target_type == TypeManager.float_type)
1327 return new FloatConstant ((float) Value, Location);
1328 if (target_type == TypeManager.double_type)
1329 return new DoubleConstant ((double) Value, Location);
1330 if (target_type == TypeManager.char_type) {
1331 if (in_checked_context){
1332 if (Value < Char.MinValue || Value > Char.MaxValue)
1333 throw new OverflowException ();
1335 return new CharConstant ((char) Value, Location);
1337 if (target_type == TypeManager.decimal_type)
1338 return new DecimalConstant ((decimal) Value, Location);
1343 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1345 if (Value >= 0 && type == TypeManager.uint64_type) {
1346 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1349 return base.ConvertImplicitly (rc, type);
1353 public class ULongConstant : IntegralConstant {
1354 public readonly ulong Value;
1356 public ULongConstant (ulong v, Location loc):
1362 protected override Expression DoResolve (ResolveContext rc)
1364 type = TypeManager.uint64_type;
1365 eclass = ExprClass.Value;
1369 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1374 public override void Emit (EmitContext ec)
1376 ec.EmitLong (unchecked ((long) Value));
1379 public override object GetValue ()
1384 public override Constant Increment ()
1386 return new ULongConstant (checked(Value + 1), loc);
1389 public override bool IsDefaultValue {
1395 public override bool IsNegative {
1401 public override bool IsOneInteger {
1407 public override bool IsZeroInteger {
1408 get { return Value == 0; }
1411 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1413 if (target_type == TypeManager.byte_type) {
1414 if (in_checked_context && Value > Byte.MaxValue)
1415 throw new OverflowException ();
1416 return new ByteConstant ((byte) Value, Location);
1418 if (target_type == TypeManager.sbyte_type) {
1419 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1420 throw new OverflowException ();
1421 return new SByteConstant ((sbyte) Value, Location);
1423 if (target_type == TypeManager.short_type) {
1424 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1425 throw new OverflowException ();
1426 return new ShortConstant ((short) Value, Location);
1428 if (target_type == TypeManager.ushort_type) {
1429 if (in_checked_context && Value > UInt16.MaxValue)
1430 throw new OverflowException ();
1431 return new UShortConstant ((ushort) Value, Location);
1433 if (target_type == TypeManager.int32_type) {
1434 if (in_checked_context && Value > UInt32.MaxValue)
1435 throw new OverflowException ();
1436 return new IntConstant ((int) Value, Location);
1438 if (target_type == TypeManager.uint32_type) {
1439 if (in_checked_context && Value > UInt32.MaxValue)
1440 throw new OverflowException ();
1441 return new UIntConstant ((uint) Value, Location);
1443 if (target_type == TypeManager.int64_type) {
1444 if (in_checked_context && Value > Int64.MaxValue)
1445 throw new OverflowException ();
1446 return new LongConstant ((long) Value, Location);
1448 if (target_type == TypeManager.float_type)
1449 return new FloatConstant ((float) Value, Location);
1450 if (target_type == TypeManager.double_type)
1451 return new DoubleConstant ((double) Value, Location);
1452 if (target_type == TypeManager.char_type) {
1453 if (in_checked_context && Value > Char.MaxValue)
1454 throw new OverflowException ();
1455 return new CharConstant ((char) Value, Location);
1457 if (target_type == TypeManager.decimal_type)
1458 return new DecimalConstant ((decimal) Value, Location);
1465 public class FloatConstant : Constant {
1468 public FloatConstant (float v, Location loc):
1474 protected override Expression DoResolve (ResolveContext rc)
1476 type = TypeManager.float_type;
1477 eclass = ExprClass.Value;
1481 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1486 public override void Emit (EmitContext ec)
1488 ec.Emit (OpCodes.Ldc_R4, Value);
1491 public override object GetValue ()
1496 public override string GetValueAsLiteral ()
1498 return Value.ToString ();
1501 public override bool IsDefaultValue {
1507 public override bool IsNegative {
1513 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1515 if (target_type == TypeManager.byte_type) {
1516 if (in_checked_context){
1517 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1518 throw new OverflowException ();
1520 return new ByteConstant ((byte) Value, Location);
1522 if (target_type == TypeManager.sbyte_type) {
1523 if (in_checked_context){
1524 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1525 throw new OverflowException ();
1527 return new SByteConstant ((sbyte) Value, Location);
1529 if (target_type == TypeManager.short_type) {
1530 if (in_checked_context){
1531 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1532 throw new OverflowException ();
1534 return new ShortConstant ((short) Value, Location);
1536 if (target_type == TypeManager.ushort_type) {
1537 if (in_checked_context){
1538 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1539 throw new OverflowException ();
1541 return new UShortConstant ((ushort) Value, Location);
1543 if (target_type == TypeManager.int32_type) {
1544 if (in_checked_context){
1545 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1546 throw new OverflowException ();
1548 return new IntConstant ((int) Value, Location);
1550 if (target_type == TypeManager.uint32_type) {
1551 if (in_checked_context){
1552 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1553 throw new OverflowException ();
1555 return new UIntConstant ((uint) Value, Location);
1557 if (target_type == TypeManager.int64_type) {
1558 if (in_checked_context){
1559 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1560 throw new OverflowException ();
1562 return new LongConstant ((long) Value, Location);
1564 if (target_type == TypeManager.uint64_type) {
1565 if (in_checked_context){
1566 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1567 throw new OverflowException ();
1569 return new ULongConstant ((ulong) Value, Location);
1571 if (target_type == TypeManager.double_type)
1572 return new DoubleConstant ((double) Value, Location);
1573 if (target_type == TypeManager.char_type) {
1574 if (in_checked_context){
1575 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1576 throw new OverflowException ();
1578 return new CharConstant ((char) Value, Location);
1580 if (target_type == TypeManager.decimal_type)
1581 return new DecimalConstant ((decimal) Value, Location);
1588 public class DoubleConstant : Constant {
1589 public double Value;
1591 public DoubleConstant (double v, Location loc):
1597 protected override Expression DoResolve (ResolveContext rc)
1599 type = TypeManager.double_type;
1600 eclass = ExprClass.Value;
1604 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1609 public override void Emit (EmitContext ec)
1611 ec.Emit (OpCodes.Ldc_R8, Value);
1614 public override object GetValue ()
1619 public override string GetValueAsLiteral ()
1621 return Value.ToString ();
1624 public override bool IsDefaultValue {
1630 public override bool IsNegative {
1636 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1638 if (target_type == TypeManager.byte_type) {
1639 if (in_checked_context){
1640 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1641 throw new OverflowException ();
1643 return new ByteConstant ((byte) Value, Location);
1645 if (target_type == TypeManager.sbyte_type) {
1646 if (in_checked_context){
1647 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1648 throw new OverflowException ();
1650 return new SByteConstant ((sbyte) Value, Location);
1652 if (target_type == TypeManager.short_type) {
1653 if (in_checked_context){
1654 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1655 throw new OverflowException ();
1657 return new ShortConstant ((short) Value, Location);
1659 if (target_type == TypeManager.ushort_type) {
1660 if (in_checked_context){
1661 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1662 throw new OverflowException ();
1664 return new UShortConstant ((ushort) Value, Location);
1666 if (target_type == TypeManager.int32_type) {
1667 if (in_checked_context){
1668 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1669 throw new OverflowException ();
1671 return new IntConstant ((int) Value, Location);
1673 if (target_type == TypeManager.uint32_type) {
1674 if (in_checked_context){
1675 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1676 throw new OverflowException ();
1678 return new UIntConstant ((uint) Value, Location);
1680 if (target_type == TypeManager.int64_type) {
1681 if (in_checked_context){
1682 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1683 throw new OverflowException ();
1685 return new LongConstant ((long) Value, Location);
1687 if (target_type == TypeManager.uint64_type) {
1688 if (in_checked_context){
1689 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1690 throw new OverflowException ();
1692 return new ULongConstant ((ulong) Value, Location);
1694 if (target_type == TypeManager.float_type)
1695 return new FloatConstant ((float) Value, Location);
1696 if (target_type == TypeManager.char_type) {
1697 if (in_checked_context){
1698 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1699 throw new OverflowException ();
1701 return new CharConstant ((char) Value, Location);
1703 if (target_type == TypeManager.decimal_type)
1704 return new DecimalConstant ((decimal) Value, Location);
1711 public class DecimalConstant : Constant {
1712 public readonly decimal Value;
1714 public DecimalConstant (decimal d, Location loc):
1720 protected override Expression DoResolve (ResolveContext rc)
1722 type = TypeManager.decimal_type;
1723 eclass = ExprClass.Value;
1727 public override object GetValue ()
1732 public override string GetValueAsLiteral ()
1734 return Value.ToString () + "M";
1737 public override void Emit (EmitContext ec)
1739 int [] words = decimal.GetBits (Value);
1740 int power = (words [3] >> 16) & 0xff;
1743 if (Value <= int.MaxValue && Value >= int.MinValue) {
1744 if (TypeManager.void_decimal_ctor_int_arg == null) {
1745 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1746 TypeManager.decimal_type, loc, TypeManager.int32_type);
1748 if (TypeManager.void_decimal_ctor_int_arg == null)
1752 ec.EmitInt ((int) Value);
1753 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1757 if (Value <= long.MaxValue && Value >= long.MinValue) {
1758 if (TypeManager.void_decimal_ctor_long_arg == null) {
1759 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1760 TypeManager.decimal_type, loc, TypeManager.int64_type);
1762 if (TypeManager.void_decimal_ctor_long_arg == null)
1766 ec.EmitLong ((long) Value);
1767 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1772 ec.EmitInt (words [0]);
1773 ec.EmitInt (words [1]);
1774 ec.EmitInt (words [2]);
1777 ec.EmitInt (words [3] >> 31);
1782 if (TypeManager.void_decimal_ctor_five_args == null) {
1783 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1784 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1785 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1787 if (TypeManager.void_decimal_ctor_five_args == null)
1791 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1794 public override bool IsDefaultValue {
1800 public override bool IsNegative {
1806 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1808 if (target_type == TypeManager.sbyte_type)
1809 return new SByteConstant ((sbyte)Value, loc);
1810 if (target_type == TypeManager.byte_type)
1811 return new ByteConstant ((byte)Value, loc);
1812 if (target_type == TypeManager.short_type)
1813 return new ShortConstant ((short)Value, loc);
1814 if (target_type == TypeManager.ushort_type)
1815 return new UShortConstant ((ushort)Value, loc);
1816 if (target_type == TypeManager.int32_type)
1817 return new IntConstant ((int)Value, loc);
1818 if (target_type == TypeManager.uint32_type)
1819 return new UIntConstant ((uint)Value, loc);
1820 if (target_type == TypeManager.int64_type)
1821 return new LongConstant ((long)Value, loc);
1822 if (target_type == TypeManager.uint64_type)
1823 return new ULongConstant ((ulong)Value, loc);
1824 if (target_type == TypeManager.char_type)
1825 return new CharConstant ((char)Value, loc);
1826 if (target_type == TypeManager.float_type)
1827 return new FloatConstant ((float)Value, loc);
1828 if (target_type == TypeManager.double_type)
1829 return new DoubleConstant ((double)Value, loc);
1836 public class StringConstant : Constant {
1837 public readonly string Value;
1839 public StringConstant (string s, Location loc):
1845 protected override Expression DoResolve (ResolveContext rc)
1847 type = TypeManager.string_type;
1848 eclass = ExprClass.Value;
1852 public override object GetValue ()
1857 public override string GetValueAsLiteral ()
1859 // FIXME: Escape the string.
1860 return "\"" + Value + "\"";
1863 public override void Emit (EmitContext ec)
1865 if (Value == null) {
1866 ec.Emit (OpCodes.Ldnull);
1871 // Use string.Empty for both literals and constants even if
1872 // it's not allowed at language level
1874 if (Value.Length == 0 && RootContext.Optimize && ec.CurrentType != TypeManager.string_type) {
1875 if (TypeManager.string_empty == null)
1876 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type);
1878 if (TypeManager.string_empty != null) {
1879 ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1884 ec.Emit (OpCodes.Ldstr, Value);
1887 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1890 if (type != targetType)
1896 public override bool IsDefaultValue {
1898 return Value == null;
1902 public override bool IsNegative {
1908 public override bool IsNull {
1910 return IsDefaultValue;
1914 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1921 // Null constant can have its own type, think of `default (Foo)'
1923 public class NullConstant : Constant
1925 public NullConstant (TypeSpec type, Location loc)
1928 eclass = ExprClass.Value;
1932 public override Expression CreateExpressionTree (ResolveContext ec)
1934 if (type == InternalType.Null || type == TypeManager.object_type) {
1935 // Optimized version, also avoids referencing literal internal type
1936 Arguments args = new Arguments (1);
1937 args.Add (new Argument (this));
1938 return CreateExpressionFactoryCall (ec, "Constant", args);
1941 return base.CreateExpressionTree (ec);
1944 protected override Expression DoResolve (ResolveContext ec)
1949 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1951 // Type it as string cast
1952 if (targetType == TypeManager.object_type || targetType == InternalType.Null)
1953 enc.Encode (TypeManager.string_type);
1955 var ac = targetType as ArrayContainer;
1957 if (ac.Rank != 1 || ac.Element.IsArray)
1958 base.EncodeAttributeValue (rc, enc, targetType);
1960 enc.Encode (uint.MaxValue);
1962 enc.Encode (byte.MaxValue);
1966 public override void Emit (EmitContext ec)
1968 ec.Emit (OpCodes.Ldnull);
1970 // Only to make verifier happy
1971 if (TypeManager.IsGenericParameter (type))
1972 ec.Emit (OpCodes.Unbox_Any, type);
1975 public override string ExprClassName {
1977 return GetSignatureForError ();
1981 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
1983 if (targetType.IsPointer) {
1984 if (IsLiteral || this is NullPointer)
1985 return new EmptyConstantCast (new NullPointer (loc), targetType);
1990 // Exlude internal compiler types
1991 if (targetType.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null)
1994 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
1997 if (TypeManager.IsReferenceType (targetType))
1998 return new NullConstant (targetType, loc);
2000 if (TypeManager.IsNullableType (targetType))
2001 return Nullable.LiftedNull.Create (targetType, loc);
2006 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
2008 return ConvertExplicitly (false, targetType);
2011 public override string GetSignatureForError ()
2016 public override object GetValue ()
2021 public override string GetValueAsLiteral ()
2023 return GetSignatureForError ();
2026 public override bool IsDefaultValue {
2027 get { return true; }
2030 public override bool IsNegative {
2031 get { return false; }
2034 public override bool IsNull {
2035 get { return true; }
2038 public override bool IsZeroInteger {
2039 get { return true; }
2044 /// The value is constant, but when emitted has a side effect. This is
2045 /// used by BitwiseAnd to ensure that the second expression is invoked
2046 /// regardless of the value of the left side.
2048 public class SideEffectConstant : Constant {
2049 public Constant value;
2050 Expression side_effect;
2052 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2055 while (side_effect is SideEffectConstant)
2056 side_effect = ((SideEffectConstant) side_effect).side_effect;
2057 this.side_effect = side_effect;
2060 protected override Expression DoResolve (ResolveContext rc)
2062 value = value.Resolve (rc);
2065 eclass = ExprClass.Value;
2069 public override object GetValue ()
2071 return value.GetValue ();
2074 public override string GetValueAsLiteral ()
2076 return value.GetValueAsLiteral ();
2079 public override void Emit (EmitContext ec)
2081 side_effect.EmitSideEffect (ec);
2085 public override void EmitSideEffect (EmitContext ec)
2087 side_effect.EmitSideEffect (ec);
2088 value.EmitSideEffect (ec);
2091 public override bool IsDefaultValue {
2092 get { return value.IsDefaultValue; }
2095 public override bool IsNegative {
2096 get { return value.IsNegative; }
2099 public override bool IsZeroInteger {
2100 get { return value.IsZeroInteger; }
2103 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2105 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2106 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);