2009-03-11 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / mcs / constant.cs
blobf141c8211105fc0be72f92192d4cf406b97669a7
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
12 namespace Mono.CSharp {
14 using System;
15 using System.Reflection.Emit;
16 using System.Collections;
18 /// <summary>
19 /// Base class for constants and literals.
20 /// </summary>
21 public abstract class Constant : Expression {
23 protected Constant (Location loc)
25 this.loc = loc;
28 /// <remarks>
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.
35 /// </remarks>
36 public abstract string AsString ();
38 override public string ToString ()
40 return this.GetType ().Name + " (" + AsString () + ")";
43 public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
45 if (value_type == TypeManager.object_type) {
46 value = GetTypedValue ();
47 return true;
50 Constant c = ImplicitConversionRequired (ec, value_type, loc);
51 if (c == null) {
52 value = null;
53 return false;
56 value = c.GetTypedValue ();
57 return true;
60 /// <summary>
61 /// This is used to obtain the actual value of the literal
62 /// cast into an object.
63 /// </summary>
64 public abstract object GetValue ();
66 public virtual object GetTypedValue ()
68 return GetValue ();
71 /// <summary>
72 /// Constants are always born in a fully resolved state
73 /// </summary>
74 public override Expression DoResolve (EmitContext ec)
76 return this;
79 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
81 if (!expl && IsLiteral &&
82 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
83 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
84 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
85 AsString (), TypeManager.CSharpName (target));
86 } else {
87 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
91 public Constant ImplicitConversionRequired (EmitContext ec, Type type, Location loc)
93 Constant c = ConvertImplicitly (type);
94 if (c == null)
95 Error_ValueCannotBeConverted (ec, loc, type, false);
96 return c;
99 public virtual Constant ConvertImplicitly (Type type)
101 if (this.type == type)
102 return this;
104 if (Convert.ImplicitNumericConversion (this, type) == null)
105 return null;
107 bool fail;
108 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
109 if (fail){
111 // We should always catch the error before this is ever
112 // reached, by calling Convert.ImplicitStandardConversionExists
114 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
115 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
118 return CreateConstant (type, constant_value, loc);
121 /// Returns a constant instance based on Type
122 /// The returned value is already resolved.
123 public static Constant CreateConstant (Type t, object v, Location loc)
125 if (t == TypeManager.int32_type)
126 return new IntConstant ((int) v, loc);
127 if (t == TypeManager.string_type)
128 return new StringConstant ((string) v, loc);
129 if (t == TypeManager.uint32_type)
130 return new UIntConstant ((uint) v, loc);
131 if (t == TypeManager.int64_type)
132 return new LongConstant ((long) v, loc);
133 if (t == TypeManager.uint64_type)
134 return new ULongConstant ((ulong) v, loc);
135 if (t == TypeManager.float_type)
136 return new FloatConstant ((float) v, loc);
137 if (t == TypeManager.double_type)
138 return new DoubleConstant ((double) v, loc);
139 if (t == TypeManager.short_type)
140 return new ShortConstant ((short)v, loc);
141 if (t == TypeManager.ushort_type)
142 return new UShortConstant ((ushort)v, loc);
143 if (t == TypeManager.sbyte_type)
144 return new SByteConstant ((sbyte)v, loc);
145 if (t == TypeManager.byte_type)
146 return new ByteConstant ((byte)v, loc);
147 if (t == TypeManager.char_type)
148 return new CharConstant ((char)v, loc);
149 if (t == TypeManager.bool_type)
150 return new BoolConstant ((bool) v, loc);
151 if (t == TypeManager.decimal_type)
152 return new DecimalConstant ((decimal) v, loc);
153 if (TypeManager.IsEnumType (t)) {
154 Type real_type = TypeManager.GetEnumUnderlyingType (t);
155 return new EnumConstant (CreateConstant (real_type, v, loc), t);
157 if (v == null && !TypeManager.IsValueType (t))
158 return new EmptyConstantCast (new NullLiteral (loc), t);
160 throw new Exception ("Unknown type for constant (" + t +
161 "), details: " + v);
164 public override Expression CreateExpressionTree (EmitContext ec)
166 ArrayList args = new ArrayList (2);
167 args.Add (new Argument (this));
168 args.Add (new Argument (
169 new TypeOf (new TypeExpression (type, loc), loc)));
171 return CreateExpressionFactoryCall ("Constant", args);
175 /// <summary>
176 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
177 /// It throws OverflowException
178 /// </summary>
179 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
180 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
182 /// <summary>
183 /// Attempts to do a compile-time folding of a constant cast.
184 /// </summary>
185 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
187 try {
188 return TryReduce (ec, target_type);
190 catch (OverflowException) {
191 if (ec.ConstantCheckState) {
192 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
193 GetValue ().ToString (), TypeManager.CSharpName (target_type));
194 } else {
195 Error_ValueCannotBeConverted (ec, loc, target_type, false);
198 return New.Constantify (target_type);
202 Constant TryReduce (EmitContext ec, Type target_type)
204 if (Type == target_type)
205 return this;
207 if (TypeManager.IsEnumType (target_type)) {
208 Constant c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type));
209 if (c == null)
210 return null;
212 return new EnumConstant (c, target_type);
215 return ConvertExplicitly (ec.ConstantCheckState, target_type);
218 public abstract Constant Increment ();
220 /// <summary>
221 /// Need to pass type as the constant can require a boxing
222 /// and in such case no optimization is possible
223 /// </summary>
224 public bool IsDefaultInitializer (Type type)
226 if (type == Type)
227 return IsDefaultValue;
229 return this is NullLiteral;
232 public abstract bool IsDefaultValue {
233 get;
236 public abstract bool IsNegative {
237 get;
241 // When constant is declared as literal
243 public virtual bool IsLiteral {
244 get { return false; }
248 // Returns true iff 1) the stack type of this is one of Object,
249 // int32, int64 and 2) this == 0 or this == null.
251 public virtual bool IsZeroInteger {
252 get { return false; }
255 public override void EmitSideEffect (EmitContext ec)
257 // do nothing
260 protected override void CloneTo (CloneContext clonectx, Expression target)
262 // CloneTo: Nothing, we do not keep any state on this expression
265 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
267 // A constant cannot be of generic type
271 public abstract class IntegralConstant : Constant {
272 protected IntegralConstant (Location loc) :
273 base (loc)
277 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
279 try {
280 ConvertExplicitly (true, target);
281 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
283 catch
285 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
286 GetValue ().ToString (), TypeManager.CSharpName (target));
291 public class BoolConstant : Constant {
292 public readonly bool Value;
294 public BoolConstant (bool val, Location loc):
295 base (loc)
297 type = TypeManager.bool_type;
298 eclass = ExprClass.Value;
300 Value = val;
303 override public string AsString ()
305 return Value ? "true" : "false";
308 public override object GetValue ()
310 return (object) Value;
314 public override void Emit (EmitContext ec)
316 if (Value)
317 ec.ig.Emit (OpCodes.Ldc_I4_1);
318 else
319 ec.ig.Emit (OpCodes.Ldc_I4_0);
322 public override Constant Increment ()
324 throw new NotSupportedException ();
327 public override bool IsDefaultValue {
328 get {
329 return !Value;
333 public override bool IsNegative {
334 get {
335 return false;
339 public override bool IsZeroInteger {
340 get { return Value == false; }
343 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
345 return null;
350 public class ByteConstant : IntegralConstant {
351 public readonly byte Value;
353 public ByteConstant (byte v, Location loc):
354 base (loc)
356 type = TypeManager.byte_type;
357 eclass = ExprClass.Value;
358 Value = v;
361 public override void Emit (EmitContext ec)
363 IntLiteral.EmitInt (ec.ig, Value);
366 public override string AsString ()
368 return Value.ToString ();
371 public override object GetValue ()
373 return Value;
376 public override Constant Increment ()
378 return new ByteConstant (checked ((byte)(Value + 1)), loc);
381 public override bool IsDefaultValue {
382 get {
383 return Value == 0;
387 public override bool IsNegative {
388 get {
389 return false;
393 public override bool IsZeroInteger {
394 get { return Value == 0; }
397 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
399 if (target_type == TypeManager.sbyte_type) {
400 if (in_checked_context){
401 if (Value > SByte.MaxValue)
402 throw new OverflowException ();
404 return new SByteConstant ((sbyte) Value, Location);
406 if (target_type == TypeManager.short_type)
407 return new ShortConstant ((short) Value, Location);
408 if (target_type == TypeManager.ushort_type)
409 return new UShortConstant ((ushort) Value, Location);
410 if (target_type == TypeManager.int32_type)
411 return new IntConstant ((int) Value, Location);
412 if (target_type == TypeManager.uint32_type)
413 return new UIntConstant ((uint) Value, Location);
414 if (target_type == TypeManager.int64_type)
415 return new LongConstant ((long) Value, Location);
416 if (target_type == TypeManager.uint64_type)
417 return new ULongConstant ((ulong) Value, Location);
418 if (target_type == TypeManager.float_type)
419 return new FloatConstant ((float) Value, Location);
420 if (target_type == TypeManager.double_type)
421 return new DoubleConstant ((double) Value, Location);
422 if (target_type == TypeManager.char_type)
423 return new CharConstant ((char) Value, Location);
424 if (target_type == TypeManager.decimal_type)
425 return new DecimalConstant ((decimal) Value, Location);
427 return null;
432 public class CharConstant : Constant {
433 public readonly char Value;
435 public CharConstant (char v, Location loc):
436 base (loc)
438 type = TypeManager.char_type;
439 eclass = ExprClass.Value;
440 Value = v;
443 public override void Emit (EmitContext ec)
445 IntLiteral.EmitInt (ec.ig, Value);
448 static public string descape (char c)
450 switch (c){
451 case '\a':
452 return "\\a";
453 case '\b':
454 return "\\b";
455 case '\n':
456 return "\\n";
457 case '\t':
458 return "\\t";
459 case '\v':
460 return "\\v";
461 case '\r':
462 return "\\r";
463 case '\\':
464 return "\\\\";
465 case '\f':
466 return "\\f";
467 case '\0':
468 return "\\0";
469 case '"':
470 return "\\\"";
471 case '\'':
472 return "\\\'";
474 return c.ToString ();
477 public override string AsString ()
479 return "\"" + descape (Value) + "\"";
482 public override object GetValue ()
484 return Value;
487 public override Constant Increment ()
489 return new CharConstant (checked ((char)(Value + 1)), loc);
492 public override bool IsDefaultValue {
493 get {
494 return Value == 0;
498 public override bool IsNegative {
499 get {
500 return false;
504 public override bool IsZeroInteger {
505 get { return Value == '\0'; }
508 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
510 if (target_type == TypeManager.byte_type) {
511 if (in_checked_context){
512 if (Value < Byte.MinValue || Value > Byte.MaxValue)
513 throw new OverflowException ();
515 return new ByteConstant ((byte) Value, Location);
517 if (target_type == TypeManager.sbyte_type) {
518 if (in_checked_context){
519 if (Value > SByte.MaxValue)
520 throw new OverflowException ();
522 return new SByteConstant ((sbyte) Value, Location);
524 if (target_type == TypeManager.short_type) {
525 if (in_checked_context){
526 if (Value > Int16.MaxValue)
527 throw new OverflowException ();
529 return new ShortConstant ((short) Value, Location);
531 if (target_type == TypeManager.int32_type)
532 return new IntConstant ((int) Value, Location);
533 if (target_type == TypeManager.uint32_type)
534 return new UIntConstant ((uint) Value, Location);
535 if (target_type == TypeManager.int64_type)
536 return new LongConstant ((long) Value, Location);
537 if (target_type == TypeManager.uint64_type)
538 return new ULongConstant ((ulong) Value, Location);
539 if (target_type == TypeManager.float_type)
540 return new FloatConstant ((float) Value, Location);
541 if (target_type == TypeManager.double_type)
542 return new DoubleConstant ((double) Value, Location);
543 if (target_type == TypeManager.decimal_type)
544 return new DecimalConstant ((decimal) Value, Location);
546 return null;
551 public class SByteConstant : IntegralConstant {
552 public readonly sbyte Value;
554 public SByteConstant (sbyte v, Location loc):
555 base (loc)
557 type = TypeManager.sbyte_type;
558 eclass = ExprClass.Value;
559 Value = v;
562 public override void Emit (EmitContext ec)
564 IntLiteral.EmitInt (ec.ig, Value);
567 public override string AsString ()
569 return Value.ToString ();
572 public override object GetValue ()
574 return Value;
577 public override Constant Increment ()
579 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
582 public override bool IsDefaultValue {
583 get {
584 return Value == 0;
588 public override bool IsNegative {
589 get {
590 return Value < 0;
594 public override bool IsZeroInteger {
595 get { return Value == 0; }
598 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
600 if (target_type == TypeManager.byte_type) {
601 if (in_checked_context && Value < 0)
602 throw new OverflowException ();
603 return new ByteConstant ((byte) Value, Location);
605 if (target_type == TypeManager.short_type)
606 return new ShortConstant ((short) Value, Location);
607 if (target_type == TypeManager.ushort_type) {
608 if (in_checked_context && Value < 0)
609 throw new OverflowException ();
610 return new UShortConstant ((ushort) Value, Location);
611 } if (target_type == TypeManager.int32_type)
612 return new IntConstant ((int) Value, Location);
613 if (target_type == TypeManager.uint32_type) {
614 if (in_checked_context && Value < 0)
615 throw new OverflowException ();
616 return new UIntConstant ((uint) Value, Location);
617 } if (target_type == TypeManager.int64_type)
618 return new LongConstant ((long) Value, Location);
619 if (target_type == TypeManager.uint64_type) {
620 if (in_checked_context && Value < 0)
621 throw new OverflowException ();
622 return new ULongConstant ((ulong) Value, Location);
624 if (target_type == TypeManager.float_type)
625 return new FloatConstant ((float) Value, Location);
626 if (target_type == TypeManager.double_type)
627 return new DoubleConstant ((double) Value, Location);
628 if (target_type == TypeManager.char_type) {
629 if (in_checked_context && Value < 0)
630 throw new OverflowException ();
631 return new CharConstant ((char) Value, Location);
633 if (target_type == TypeManager.decimal_type)
634 return new DecimalConstant ((decimal) Value, Location);
636 return null;
641 public class ShortConstant : IntegralConstant {
642 public readonly short Value;
644 public ShortConstant (short v, Location loc):
645 base (loc)
647 type = TypeManager.short_type;
648 eclass = ExprClass.Value;
649 Value = v;
652 public override void Emit (EmitContext ec)
654 IntLiteral.EmitInt (ec.ig, Value);
657 public override string AsString ()
659 return Value.ToString ();
662 public override object GetValue ()
664 return Value;
667 public override Constant Increment ()
669 return new ShortConstant (checked((short)(Value + 1)), loc);
672 public override bool IsDefaultValue {
673 get {
674 return Value == 0;
678 public override bool IsZeroInteger {
679 get { return Value == 0; }
682 public override bool IsNegative {
683 get {
684 return Value < 0;
688 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
690 if (target_type == TypeManager.byte_type) {
691 if (in_checked_context){
692 if (Value < Byte.MinValue || Value > Byte.MaxValue)
693 throw new OverflowException ();
695 return new ByteConstant ((byte) Value, Location);
697 if (target_type == TypeManager.sbyte_type) {
698 if (in_checked_context){
699 if (Value < SByte.MinValue || Value > SByte.MaxValue)
700 throw new OverflowException ();
702 return new SByteConstant ((sbyte) Value, Location);
704 if (target_type == TypeManager.ushort_type) {
705 if (in_checked_context && Value < 0)
706 throw new OverflowException ();
708 return new UShortConstant ((ushort) Value, Location);
710 if (target_type == TypeManager.int32_type)
711 return new IntConstant ((int) Value, Location);
712 if (target_type == TypeManager.uint32_type) {
713 if (in_checked_context && Value < 0)
714 throw new OverflowException ();
715 return new UIntConstant ((uint) Value, Location);
717 if (target_type == TypeManager.int64_type)
718 return new LongConstant ((long) Value, Location);
719 if (target_type == TypeManager.uint64_type) {
720 if (in_checked_context && Value < 0)
721 throw new OverflowException ();
722 return new ULongConstant ((ulong) Value, Location);
724 if (target_type == TypeManager.float_type)
725 return new FloatConstant ((float) Value, Location);
726 if (target_type == TypeManager.double_type)
727 return new DoubleConstant ((double) Value, Location);
728 if (target_type == TypeManager.char_type) {
729 if (in_checked_context){
730 if (Value < Char.MinValue)
731 throw new OverflowException ();
733 return new CharConstant ((char) Value, Location);
735 if (target_type == TypeManager.decimal_type)
736 return new DecimalConstant ((decimal) Value, Location);
738 return null;
743 public class UShortConstant : IntegralConstant {
744 public readonly ushort Value;
746 public UShortConstant (ushort v, Location loc):
747 base (loc)
749 type = TypeManager.ushort_type;
750 eclass = ExprClass.Value;
751 Value = v;
754 public override void Emit (EmitContext ec)
756 IntLiteral.EmitInt (ec.ig, Value);
759 public override string AsString ()
761 return Value.ToString ();
764 public override object GetValue ()
766 return Value;
769 public override Constant Increment ()
771 return new UShortConstant (checked((ushort)(Value + 1)), loc);
774 public override bool IsDefaultValue {
775 get {
776 return Value == 0;
780 public override bool IsNegative {
781 get {
782 return false;
786 public override bool IsZeroInteger {
787 get { return Value == 0; }
790 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
792 if (target_type == TypeManager.byte_type) {
793 if (in_checked_context){
794 if (Value > Byte.MaxValue)
795 throw new OverflowException ();
797 return new ByteConstant ((byte) Value, Location);
799 if (target_type == TypeManager.sbyte_type) {
800 if (in_checked_context){
801 if (Value > SByte.MaxValue)
802 throw new OverflowException ();
804 return new SByteConstant ((sbyte) Value, Location);
806 if (target_type == TypeManager.short_type) {
807 if (in_checked_context){
808 if (Value > Int16.MaxValue)
809 throw new OverflowException ();
811 return new ShortConstant ((short) Value, Location);
813 if (target_type == TypeManager.int32_type)
814 return new IntConstant ((int) Value, Location);
815 if (target_type == TypeManager.uint32_type)
816 return new UIntConstant ((uint) Value, Location);
817 if (target_type == TypeManager.int64_type)
818 return new LongConstant ((long) Value, Location);
819 if (target_type == TypeManager.uint64_type)
820 return new ULongConstant ((ulong) Value, Location);
821 if (target_type == TypeManager.float_type)
822 return new FloatConstant ((float) Value, Location);
823 if (target_type == TypeManager.double_type)
824 return new DoubleConstant ((double) Value, Location);
825 if (target_type == TypeManager.char_type) {
826 if (in_checked_context){
827 if (Value > Char.MaxValue)
828 throw new OverflowException ();
830 return new CharConstant ((char) Value, Location);
832 if (target_type == TypeManager.decimal_type)
833 return new DecimalConstant ((decimal) Value, Location);
835 return null;
839 public class IntConstant : IntegralConstant {
840 public readonly int Value;
842 public IntConstant (int v, Location loc):
843 base (loc)
845 type = TypeManager.int32_type;
846 eclass = ExprClass.Value;
847 Value = v;
850 static public void EmitInt (ILGenerator ig, int i)
852 switch (i){
853 case -1:
854 ig.Emit (OpCodes.Ldc_I4_M1);
855 break;
857 case 0:
858 ig.Emit (OpCodes.Ldc_I4_0);
859 break;
861 case 1:
862 ig.Emit (OpCodes.Ldc_I4_1);
863 break;
865 case 2:
866 ig.Emit (OpCodes.Ldc_I4_2);
867 break;
869 case 3:
870 ig.Emit (OpCodes.Ldc_I4_3);
871 break;
873 case 4:
874 ig.Emit (OpCodes.Ldc_I4_4);
875 break;
877 case 5:
878 ig.Emit (OpCodes.Ldc_I4_5);
879 break;
881 case 6:
882 ig.Emit (OpCodes.Ldc_I4_6);
883 break;
885 case 7:
886 ig.Emit (OpCodes.Ldc_I4_7);
887 break;
889 case 8:
890 ig.Emit (OpCodes.Ldc_I4_8);
891 break;
893 default:
894 if (i >= -128 && i <= 127){
895 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
896 } else
897 ig.Emit (OpCodes.Ldc_I4, i);
898 break;
902 public override void Emit (EmitContext ec)
904 EmitInt (ec.ig, Value);
907 public override string AsString ()
909 return Value.ToString ();
912 public override object GetValue ()
914 return Value;
917 public override Constant Increment ()
919 return new IntConstant (checked(Value + 1), loc);
922 public override bool IsDefaultValue {
923 get {
924 return Value == 0;
928 public override bool IsNegative {
929 get {
930 return Value < 0;
934 public override bool IsZeroInteger {
935 get { return Value == 0; }
938 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
940 if (target_type == TypeManager.byte_type) {
941 if (in_checked_context){
942 if (Value < Byte.MinValue || Value > Byte.MaxValue)
943 throw new OverflowException ();
945 return new ByteConstant ((byte) Value, Location);
947 if (target_type == TypeManager.sbyte_type) {
948 if (in_checked_context){
949 if (Value < SByte.MinValue || Value > SByte.MaxValue)
950 throw new OverflowException ();
952 return new SByteConstant ((sbyte) Value, Location);
954 if (target_type == TypeManager.short_type) {
955 if (in_checked_context){
956 if (Value < Int16.MinValue || Value > Int16.MaxValue)
957 throw new OverflowException ();
959 return new ShortConstant ((short) Value, Location);
961 if (target_type == TypeManager.ushort_type) {
962 if (in_checked_context){
963 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
964 throw new OverflowException ();
966 return new UShortConstant ((ushort) Value, Location);
968 if (target_type == TypeManager.uint32_type) {
969 if (in_checked_context){
970 if (Value < UInt32.MinValue)
971 throw new OverflowException ();
973 return new UIntConstant ((uint) Value, Location);
975 if (target_type == TypeManager.int64_type)
976 return new LongConstant ((long) Value, Location);
977 if (target_type == TypeManager.uint64_type) {
978 if (in_checked_context && Value < 0)
979 throw new OverflowException ();
980 return new ULongConstant ((ulong) Value, Location);
982 if (target_type == TypeManager.float_type)
983 return new FloatConstant ((float) Value, Location);
984 if (target_type == TypeManager.double_type)
985 return new DoubleConstant ((double) Value, Location);
986 if (target_type == TypeManager.char_type) {
987 if (in_checked_context){
988 if (Value < Char.MinValue || Value > Char.MaxValue)
989 throw new OverflowException ();
991 return new CharConstant ((char) Value, Location);
993 if (target_type == TypeManager.decimal_type)
994 return new DecimalConstant ((decimal) Value, Location);
996 return null;
999 public override Constant ConvertImplicitly (Type type)
1001 if (this.type == type)
1002 return this;
1004 Constant c = TryImplicitIntConversion (type);
1005 if (c != null)
1006 return c;
1008 return base.ConvertImplicitly (type);
1011 /// <summary>
1012 /// Attempts to perform an implicit constant conversion of the IntConstant
1013 /// into a different data type using casts (See Implicit Constant
1014 /// Expression Conversions)
1015 /// </summary>
1016 Constant TryImplicitIntConversion (Type target_type)
1018 if (target_type == TypeManager.sbyte_type) {
1019 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1020 return new SByteConstant ((sbyte) Value, loc);
1022 else if (target_type == TypeManager.byte_type) {
1023 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1024 return new ByteConstant ((byte) Value, loc);
1026 else if (target_type == TypeManager.short_type) {
1027 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1028 return new ShortConstant ((short) Value, loc);
1030 else if (target_type == TypeManager.ushort_type) {
1031 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1032 return new UShortConstant ((ushort) Value, loc);
1034 else if (target_type == TypeManager.uint32_type) {
1035 if (Value >= 0)
1036 return new UIntConstant ((uint) Value, loc);
1038 else if (target_type == TypeManager.uint64_type) {
1040 // we can optimize this case: a positive int32
1041 // always fits on a uint64. But we need an opcode
1042 // to do it.
1044 if (Value >= 0)
1045 return new ULongConstant ((ulong) Value, loc);
1047 else if (target_type == TypeManager.double_type)
1048 return new DoubleConstant ((double) Value, loc);
1049 else if (target_type == TypeManager.float_type)
1050 return new FloatConstant ((float) Value, loc);
1052 return null;
1056 public class UIntConstant : IntegralConstant {
1057 public readonly uint Value;
1059 public UIntConstant (uint v, Location loc):
1060 base (loc)
1062 type = TypeManager.uint32_type;
1063 eclass = ExprClass.Value;
1064 Value = v;
1067 public override void Emit (EmitContext ec)
1069 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1072 public override string AsString ()
1074 return Value.ToString ();
1077 public override object GetValue ()
1079 return Value;
1082 public override Constant Increment ()
1084 return new UIntConstant (checked(Value + 1), loc);
1087 public override bool IsDefaultValue {
1088 get {
1089 return Value == 0;
1093 public override bool IsNegative {
1094 get {
1095 return false;
1099 public override bool IsZeroInteger {
1100 get { return Value == 0; }
1103 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1105 if (target_type == TypeManager.byte_type) {
1106 if (in_checked_context){
1107 if (Value < Char.MinValue || Value > Char.MaxValue)
1108 throw new OverflowException ();
1110 return new ByteConstant ((byte) Value, Location);
1112 if (target_type == TypeManager.sbyte_type) {
1113 if (in_checked_context){
1114 if (Value > SByte.MaxValue)
1115 throw new OverflowException ();
1117 return new SByteConstant ((sbyte) Value, Location);
1119 if (target_type == TypeManager.short_type) {
1120 if (in_checked_context){
1121 if (Value > Int16.MaxValue)
1122 throw new OverflowException ();
1124 return new ShortConstant ((short) Value, Location);
1126 if (target_type == TypeManager.ushort_type) {
1127 if (in_checked_context){
1128 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1129 throw new OverflowException ();
1131 return new UShortConstant ((ushort) Value, Location);
1133 if (target_type == TypeManager.int32_type) {
1134 if (in_checked_context){
1135 if (Value > Int32.MaxValue)
1136 throw new OverflowException ();
1138 return new IntConstant ((int) Value, Location);
1140 if (target_type == TypeManager.int64_type)
1141 return new LongConstant ((long) Value, Location);
1142 if (target_type == TypeManager.uint64_type)
1143 return new ULongConstant ((ulong) Value, Location);
1144 if (target_type == TypeManager.float_type)
1145 return new FloatConstant ((float) Value, Location);
1146 if (target_type == TypeManager.double_type)
1147 return new DoubleConstant ((double) Value, Location);
1148 if (target_type == TypeManager.char_type) {
1149 if (in_checked_context){
1150 if (Value < Char.MinValue || Value > Char.MaxValue)
1151 throw new OverflowException ();
1153 return new CharConstant ((char) Value, Location);
1155 if (target_type == TypeManager.decimal_type)
1156 return new DecimalConstant ((decimal) Value, Location);
1158 return null;
1163 public class LongConstant : IntegralConstant {
1164 public readonly long Value;
1166 public LongConstant (long v, Location loc):
1167 base (loc)
1169 type = TypeManager.int64_type;
1170 eclass = ExprClass.Value;
1171 Value = v;
1174 public override void Emit (EmitContext ec)
1176 EmitLong (ec.ig, Value);
1179 static public void EmitLong (ILGenerator ig, long l)
1181 if (l >= int.MinValue && l <= int.MaxValue) {
1182 IntLiteral.EmitInt (ig, unchecked ((int) l));
1183 ig.Emit (OpCodes.Conv_I8);
1184 return;
1187 if (l >= 0 && l <= uint.MaxValue) {
1188 IntLiteral.EmitInt (ig, unchecked ((int) l));
1189 ig.Emit (OpCodes.Conv_U8);
1190 return;
1193 ig.Emit (OpCodes.Ldc_I8, l);
1196 public override string AsString ()
1198 return Value.ToString ();
1201 public override object GetValue ()
1203 return Value;
1206 public override Constant Increment ()
1208 return new LongConstant (checked(Value + 1), loc);
1211 public override bool IsDefaultValue {
1212 get {
1213 return Value == 0;
1217 public override bool IsNegative {
1218 get {
1219 return Value < 0;
1223 public override bool IsZeroInteger {
1224 get { return Value == 0; }
1227 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1229 if (target_type == TypeManager.byte_type) {
1230 if (in_checked_context){
1231 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1232 throw new OverflowException ();
1234 return new ByteConstant ((byte) Value, Location);
1236 if (target_type == TypeManager.sbyte_type) {
1237 if (in_checked_context){
1238 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1239 throw new OverflowException ();
1241 return new SByteConstant ((sbyte) Value, Location);
1243 if (target_type == TypeManager.short_type) {
1244 if (in_checked_context){
1245 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1246 throw new OverflowException ();
1248 return new ShortConstant ((short) Value, Location);
1250 if (target_type == TypeManager.ushort_type) {
1251 if (in_checked_context){
1252 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1253 throw new OverflowException ();
1255 return new UShortConstant ((ushort) Value, Location);
1257 if (target_type == TypeManager.int32_type) {
1258 if (in_checked_context){
1259 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1260 throw new OverflowException ();
1262 return new IntConstant ((int) Value, Location);
1264 if (target_type == TypeManager.uint32_type) {
1265 if (in_checked_context){
1266 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1267 throw new OverflowException ();
1269 return new UIntConstant ((uint) Value, Location);
1271 if (target_type == TypeManager.uint64_type) {
1272 if (in_checked_context && Value < 0)
1273 throw new OverflowException ();
1274 return new ULongConstant ((ulong) Value, Location);
1276 if (target_type == TypeManager.float_type)
1277 return new FloatConstant ((float) Value, Location);
1278 if (target_type == TypeManager.double_type)
1279 return new DoubleConstant ((double) Value, Location);
1280 if (target_type == TypeManager.char_type) {
1281 if (in_checked_context){
1282 if (Value < Char.MinValue || Value > Char.MaxValue)
1283 throw new OverflowException ();
1285 return new CharConstant ((char) Value, Location);
1287 if (target_type == TypeManager.decimal_type)
1288 return new DecimalConstant ((decimal) Value, Location);
1290 return null;
1293 public override Constant ConvertImplicitly (Type type)
1295 if (Value >= 0 && type == TypeManager.uint64_type) {
1296 return new ULongConstant ((ulong) Value, loc);
1299 return base.ConvertImplicitly (type);
1303 public class ULongConstant : IntegralConstant {
1304 public readonly ulong Value;
1306 public ULongConstant (ulong v, Location loc):
1307 base (loc)
1309 type = TypeManager.uint64_type;
1310 eclass = ExprClass.Value;
1311 Value = v;
1314 public override void Emit (EmitContext ec)
1316 ILGenerator ig = ec.ig;
1318 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1321 public override string AsString ()
1323 return Value.ToString ();
1326 public override object GetValue ()
1328 return Value;
1331 public override Constant Increment ()
1333 return new ULongConstant (checked(Value + 1), loc);
1336 public override bool IsDefaultValue {
1337 get {
1338 return Value == 0;
1342 public override bool IsNegative {
1343 get {
1344 return false;
1348 public override bool IsZeroInteger {
1349 get { return Value == 0; }
1352 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1354 if (target_type == TypeManager.byte_type) {
1355 if (in_checked_context && Value > Byte.MaxValue)
1356 throw new OverflowException ();
1357 return new ByteConstant ((byte) Value, Location);
1359 if (target_type == TypeManager.sbyte_type) {
1360 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1361 throw new OverflowException ();
1362 return new SByteConstant ((sbyte) Value, Location);
1364 if (target_type == TypeManager.short_type) {
1365 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1366 throw new OverflowException ();
1367 return new ShortConstant ((short) Value, Location);
1369 if (target_type == TypeManager.ushort_type) {
1370 if (in_checked_context && Value > UInt16.MaxValue)
1371 throw new OverflowException ();
1372 return new UShortConstant ((ushort) Value, Location);
1374 if (target_type == TypeManager.int32_type) {
1375 if (in_checked_context && Value > UInt32.MaxValue)
1376 throw new OverflowException ();
1377 return new IntConstant ((int) Value, Location);
1379 if (target_type == TypeManager.uint32_type) {
1380 if (in_checked_context && Value > UInt32.MaxValue)
1381 throw new OverflowException ();
1382 return new UIntConstant ((uint) Value, Location);
1384 if (target_type == TypeManager.int64_type) {
1385 if (in_checked_context && Value > Int64.MaxValue)
1386 throw new OverflowException ();
1387 return new LongConstant ((long) Value, Location);
1389 if (target_type == TypeManager.float_type)
1390 return new FloatConstant ((float) Value, Location);
1391 if (target_type == TypeManager.double_type)
1392 return new DoubleConstant ((double) Value, Location);
1393 if (target_type == TypeManager.char_type) {
1394 if (in_checked_context && Value > Char.MaxValue)
1395 throw new OverflowException ();
1396 return new CharConstant ((char) Value, Location);
1398 if (target_type == TypeManager.decimal_type)
1399 return new DecimalConstant ((decimal) Value, Location);
1401 return null;
1406 public class FloatConstant : Constant {
1407 public float Value;
1409 public FloatConstant (float v, Location loc):
1410 base (loc)
1412 type = TypeManager.float_type;
1413 eclass = ExprClass.Value;
1414 Value = v;
1417 public override void Emit (EmitContext ec)
1419 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1422 public override string AsString ()
1424 return Value.ToString ();
1427 public override object GetValue ()
1429 return Value;
1432 public override Constant Increment ()
1434 return new FloatConstant (checked(Value + 1), loc);
1437 public override bool IsDefaultValue {
1438 get {
1439 return Value == 0;
1443 public override bool IsNegative {
1444 get {
1445 return Value < 0;
1449 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1451 if (target_type == TypeManager.byte_type) {
1452 if (in_checked_context){
1453 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1454 throw new OverflowException ();
1456 return new ByteConstant ((byte) Value, Location);
1458 if (target_type == TypeManager.sbyte_type) {
1459 if (in_checked_context){
1460 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1461 throw new OverflowException ();
1463 return new SByteConstant ((sbyte) Value, Location);
1465 if (target_type == TypeManager.short_type) {
1466 if (in_checked_context){
1467 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1468 throw new OverflowException ();
1470 return new ShortConstant ((short) Value, Location);
1472 if (target_type == TypeManager.ushort_type) {
1473 if (in_checked_context){
1474 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1475 throw new OverflowException ();
1477 return new UShortConstant ((ushort) Value, Location);
1479 if (target_type == TypeManager.int32_type) {
1480 if (in_checked_context){
1481 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1482 throw new OverflowException ();
1484 return new IntConstant ((int) Value, Location);
1486 if (target_type == TypeManager.uint32_type) {
1487 if (in_checked_context){
1488 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1489 throw new OverflowException ();
1491 return new UIntConstant ((uint) Value, Location);
1493 if (target_type == TypeManager.int64_type) {
1494 if (in_checked_context){
1495 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1496 throw new OverflowException ();
1498 return new LongConstant ((long) Value, Location);
1500 if (target_type == TypeManager.uint64_type) {
1501 if (in_checked_context){
1502 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1503 throw new OverflowException ();
1505 return new ULongConstant ((ulong) Value, Location);
1507 if (target_type == TypeManager.double_type)
1508 return new DoubleConstant ((double) Value, Location);
1509 if (target_type == TypeManager.char_type) {
1510 if (in_checked_context){
1511 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1512 throw new OverflowException ();
1514 return new CharConstant ((char) Value, Location);
1516 if (target_type == TypeManager.decimal_type)
1517 return new DecimalConstant ((decimal) Value, Location);
1519 return null;
1524 public class DoubleConstant : Constant {
1525 public double Value;
1527 public DoubleConstant (double v, Location loc):
1528 base (loc)
1530 type = TypeManager.double_type;
1531 eclass = ExprClass.Value;
1532 Value = v;
1535 public override void Emit (EmitContext ec)
1537 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1540 public override string AsString ()
1542 return Value.ToString ();
1545 public override object GetValue ()
1547 return Value;
1550 public override Constant Increment ()
1552 return new DoubleConstant (checked(Value + 1), loc);
1555 public override bool IsDefaultValue {
1556 get {
1557 return Value == 0;
1561 public override bool IsNegative {
1562 get {
1563 return Value < 0;
1567 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1569 if (target_type == TypeManager.byte_type) {
1570 if (in_checked_context){
1571 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1572 throw new OverflowException ();
1574 return new ByteConstant ((byte) Value, Location);
1576 if (target_type == TypeManager.sbyte_type) {
1577 if (in_checked_context){
1578 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1579 throw new OverflowException ();
1581 return new SByteConstant ((sbyte) Value, Location);
1583 if (target_type == TypeManager.short_type) {
1584 if (in_checked_context){
1585 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1586 throw new OverflowException ();
1588 return new ShortConstant ((short) Value, Location);
1590 if (target_type == TypeManager.ushort_type) {
1591 if (in_checked_context){
1592 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1593 throw new OverflowException ();
1595 return new UShortConstant ((ushort) Value, Location);
1597 if (target_type == TypeManager.int32_type) {
1598 if (in_checked_context){
1599 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1600 throw new OverflowException ();
1602 return new IntConstant ((int) Value, Location);
1604 if (target_type == TypeManager.uint32_type) {
1605 if (in_checked_context){
1606 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1607 throw new OverflowException ();
1609 return new UIntConstant ((uint) Value, Location);
1611 if (target_type == TypeManager.int64_type) {
1612 if (in_checked_context){
1613 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1614 throw new OverflowException ();
1616 return new LongConstant ((long) Value, Location);
1618 if (target_type == TypeManager.uint64_type) {
1619 if (in_checked_context){
1620 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1621 throw new OverflowException ();
1623 return new ULongConstant ((ulong) Value, Location);
1625 if (target_type == TypeManager.float_type)
1626 return new FloatConstant ((float) Value, Location);
1627 if (target_type == TypeManager.char_type) {
1628 if (in_checked_context){
1629 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1630 throw new OverflowException ();
1632 return new CharConstant ((char) Value, Location);
1634 if (target_type == TypeManager.decimal_type)
1635 return new DecimalConstant ((decimal) Value, Location);
1637 return null;
1642 public class DecimalConstant : Constant {
1643 public readonly decimal Value;
1645 public DecimalConstant (decimal d, Location loc):
1646 base (loc)
1648 type = TypeManager.decimal_type;
1649 eclass = ExprClass.Value;
1650 Value = d;
1653 override public string AsString ()
1655 return Value.ToString () + "M";
1658 public override object GetValue ()
1660 return (object) Value;
1663 public override void Emit (EmitContext ec)
1665 ILGenerator ig = ec.ig;
1667 int [] words = Decimal.GetBits (Value);
1668 int power = (words [3] >> 16) & 0xff;
1670 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1672 if (TypeManager.void_decimal_ctor_int_arg == null) {
1673 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1674 TypeManager.decimal_type, loc, TypeManager.int32_type);
1676 if (TypeManager.void_decimal_ctor_int_arg == null)
1677 return;
1680 IntConstant.EmitInt (ig, (int)Value);
1681 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1682 return;
1687 // FIXME: we could optimize this, and call a better
1688 // constructor
1691 IntConstant.EmitInt (ig, words [0]);
1692 IntConstant.EmitInt (ig, words [1]);
1693 IntConstant.EmitInt (ig, words [2]);
1695 // sign
1696 IntConstant.EmitInt (ig, words [3] >> 31);
1698 // power
1699 IntConstant.EmitInt (ig, power);
1701 if (TypeManager.void_decimal_ctor_five_args == null) {
1702 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1703 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1704 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1706 if (TypeManager.void_decimal_ctor_five_args == null)
1707 return;
1710 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1713 public override Constant Increment ()
1715 return new DecimalConstant (checked (Value + 1), loc);
1718 public override bool IsDefaultValue {
1719 get {
1720 return Value == 0;
1724 public override bool IsNegative {
1725 get {
1726 return Value < 0;
1730 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1732 if (target_type == TypeManager.sbyte_type)
1733 return new SByteConstant ((sbyte)Value, loc);
1734 if (target_type == TypeManager.byte_type)
1735 return new ByteConstant ((byte)Value, loc);
1736 if (target_type == TypeManager.short_type)
1737 return new ShortConstant ((short)Value, loc);
1738 if (target_type == TypeManager.ushort_type)
1739 return new UShortConstant ((ushort)Value, loc);
1740 if (target_type == TypeManager.int32_type)
1741 return new IntConstant ((int)Value, loc);
1742 if (target_type == TypeManager.uint32_type)
1743 return new UIntConstant ((uint)Value, loc);
1744 if (target_type == TypeManager.int64_type)
1745 return new LongConstant ((long)Value, loc);
1746 if (target_type == TypeManager.uint64_type)
1747 return new ULongConstant ((ulong)Value, loc);
1748 if (target_type == TypeManager.char_type)
1749 return new CharConstant ((char)Value, loc);
1750 if (target_type == TypeManager.float_type)
1751 return new FloatConstant ((float)Value, loc);
1752 if (target_type == TypeManager.double_type)
1753 return new DoubleConstant ((double)Value, loc);
1755 return null;
1760 public class StringConstant : Constant {
1761 public readonly string Value;
1763 public StringConstant (string s, Location loc):
1764 base (loc)
1766 type = TypeManager.string_type;
1767 eclass = ExprClass.Value;
1768 Value = s;
1771 // FIXME: Escape the string.
1772 override public string AsString ()
1774 return "\"" + Value + "\"";
1777 public override object GetValue ()
1779 return Value;
1782 public override void Emit (EmitContext ec)
1784 if (Value == null) {
1785 ec.ig.Emit (OpCodes.Ldnull);
1786 return;
1790 // Use string.Empty for both literals and constants even if
1791 // it's not allowed at language level
1793 if (Value.Length == 0 && RootContext.Optimize && ec.TypeContainer.TypeBuilder != TypeManager.string_type) {
1794 if (TypeManager.string_empty == null)
1795 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
1797 if (TypeManager.string_empty != null) {
1798 ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1799 return;
1803 ec.ig.Emit (OpCodes.Ldstr, Value);
1806 public override Constant Increment ()
1808 throw new NotSupportedException ();
1811 public override bool IsDefaultValue {
1812 get {
1813 return Value == null;
1817 public override bool IsNegative {
1818 get {
1819 return false;
1823 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1825 return null;
1829 /// <summary>
1830 /// The value is constant, but when emitted has a side effect. This is
1831 /// used by BitwiseAnd to ensure that the second expression is invoked
1832 /// regardless of the value of the left side.
1833 /// </summary>
1835 public class SideEffectConstant : Constant {
1836 public Constant value;
1837 Expression side_effect;
1839 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
1841 this.value = value;
1842 while (side_effect is SideEffectConstant)
1843 side_effect = ((SideEffectConstant) side_effect).side_effect;
1844 this.side_effect = side_effect;
1845 eclass = ExprClass.Value;
1846 type = value.Type;
1849 public override string AsString ()
1851 return value.AsString ();
1854 public override object GetValue ()
1856 return value.GetValue ();
1859 public override void Emit (EmitContext ec)
1861 side_effect.EmitSideEffect (ec);
1862 value.Emit (ec);
1865 public override void EmitSideEffect (EmitContext ec)
1867 side_effect.EmitSideEffect (ec);
1868 value.EmitSideEffect (ec);
1871 public override bool IsDefaultValue {
1872 get { return value.IsDefaultValue; }
1875 public override Constant Increment ()
1877 throw new NotSupportedException ();
1880 public override bool IsNegative {
1881 get { return value.IsNegative; }
1884 public override bool IsZeroInteger {
1885 get { return value.IsZeroInteger; }
1888 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1890 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
1891 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);