2009-07-20 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / constant.cs
blob3cc2bb672dfcc5beaf8f771e731a90bed4332c6a
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 Arguments args = new Arguments (2);
167 args.Add (new Argument (this));
168 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
170 return CreateExpressionFactoryCall ("Constant", args);
174 /// <summary>
175 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
176 /// It throws OverflowException
177 /// </summary>
178 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
179 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
181 /// <summary>
182 /// Attempts to do a compile-time folding of a constant cast.
183 /// </summary>
184 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
186 try {
187 return TryReduce (ec, target_type);
189 catch (OverflowException) {
190 if (ec.ConstantCheckState) {
191 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
192 GetValue ().ToString (), TypeManager.CSharpName (target_type));
193 } else {
194 Error_ValueCannotBeConverted (ec, loc, target_type, false);
197 return New.Constantify (target_type);
201 Constant TryReduce (EmitContext ec, Type target_type)
203 if (Type == target_type)
204 return this;
206 if (TypeManager.IsEnumType (target_type)) {
207 Constant c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type));
208 if (c == null)
209 return null;
211 return new EnumConstant (c, target_type);
214 return ConvertExplicitly (ec.ConstantCheckState, target_type);
217 public abstract Constant Increment ();
219 /// <summary>
220 /// Need to pass type as the constant can require a boxing
221 /// and in such case no optimization is possible
222 /// </summary>
223 public bool IsDefaultInitializer (Type type)
225 if (type == Type)
226 return IsDefaultValue;
228 return this is NullLiteral;
231 public abstract bool IsDefaultValue {
232 get;
235 public abstract bool IsNegative {
236 get;
240 // When constant is declared as literal
242 public virtual bool IsLiteral {
243 get { return false; }
247 // Returns true iff 1) the stack type of this is one of Object,
248 // int32, int64 and 2) this == 0 or this == null.
250 public virtual bool IsZeroInteger {
251 get { return false; }
254 public override void EmitSideEffect (EmitContext ec)
256 // do nothing
259 protected override void CloneTo (CloneContext clonectx, Expression target)
261 // CloneTo: Nothing, we do not keep any state on this expression
264 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
266 // A constant cannot be of generic type
270 public abstract class IntegralConstant : Constant {
271 protected IntegralConstant (Location loc) :
272 base (loc)
276 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
278 try {
279 ConvertExplicitly (true, target);
280 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
282 catch
284 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
285 GetValue ().ToString (), TypeManager.CSharpName (target));
290 public class BoolConstant : Constant {
291 public readonly bool Value;
293 public BoolConstant (bool val, Location loc):
294 base (loc)
296 type = TypeManager.bool_type;
297 eclass = ExprClass.Value;
299 Value = val;
302 override public string AsString ()
304 return Value ? "true" : "false";
307 public override object GetValue ()
309 return (object) Value;
313 public override void Emit (EmitContext ec)
315 if (Value)
316 ec.ig.Emit (OpCodes.Ldc_I4_1);
317 else
318 ec.ig.Emit (OpCodes.Ldc_I4_0);
321 public override Constant Increment ()
323 throw new NotSupportedException ();
326 public override bool IsDefaultValue {
327 get {
328 return !Value;
332 public override bool IsNegative {
333 get {
334 return false;
338 public override bool IsZeroInteger {
339 get { return Value == false; }
342 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
344 return null;
349 public class ByteConstant : IntegralConstant {
350 public readonly byte Value;
352 public ByteConstant (byte v, Location loc):
353 base (loc)
355 type = TypeManager.byte_type;
356 eclass = ExprClass.Value;
357 Value = v;
360 public override void Emit (EmitContext ec)
362 IntLiteral.EmitInt (ec.ig, Value);
365 public override string AsString ()
367 return Value.ToString ();
370 public override object GetValue ()
372 return Value;
375 public override Constant Increment ()
377 return new ByteConstant (checked ((byte)(Value + 1)), loc);
380 public override bool IsDefaultValue {
381 get {
382 return Value == 0;
386 public override bool IsNegative {
387 get {
388 return false;
392 public override bool IsZeroInteger {
393 get { return Value == 0; }
396 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
398 if (target_type == TypeManager.sbyte_type) {
399 if (in_checked_context){
400 if (Value > SByte.MaxValue)
401 throw new OverflowException ();
403 return new SByteConstant ((sbyte) Value, Location);
405 if (target_type == TypeManager.short_type)
406 return new ShortConstant ((short) Value, Location);
407 if (target_type == TypeManager.ushort_type)
408 return new UShortConstant ((ushort) Value, Location);
409 if (target_type == TypeManager.int32_type)
410 return new IntConstant ((int) Value, Location);
411 if (target_type == TypeManager.uint32_type)
412 return new UIntConstant ((uint) Value, Location);
413 if (target_type == TypeManager.int64_type)
414 return new LongConstant ((long) Value, Location);
415 if (target_type == TypeManager.uint64_type)
416 return new ULongConstant ((ulong) Value, Location);
417 if (target_type == TypeManager.float_type)
418 return new FloatConstant ((float) Value, Location);
419 if (target_type == TypeManager.double_type)
420 return new DoubleConstant ((double) Value, Location);
421 if (target_type == TypeManager.char_type)
422 return new CharConstant ((char) Value, Location);
423 if (target_type == TypeManager.decimal_type)
424 return new DecimalConstant ((decimal) Value, Location);
426 return null;
431 public class CharConstant : Constant {
432 public readonly char Value;
434 public CharConstant (char v, Location loc):
435 base (loc)
437 type = TypeManager.char_type;
438 eclass = ExprClass.Value;
439 Value = v;
442 public override void Emit (EmitContext ec)
444 IntLiteral.EmitInt (ec.ig, Value);
447 static public string descape (char c)
449 switch (c){
450 case '\a':
451 return "\\a";
452 case '\b':
453 return "\\b";
454 case '\n':
455 return "\\n";
456 case '\t':
457 return "\\t";
458 case '\v':
459 return "\\v";
460 case '\r':
461 return "\\r";
462 case '\\':
463 return "\\\\";
464 case '\f':
465 return "\\f";
466 case '\0':
467 return "\\0";
468 case '"':
469 return "\\\"";
470 case '\'':
471 return "\\\'";
473 return c.ToString ();
476 public override string AsString ()
478 return "\"" + descape (Value) + "\"";
481 public override object GetValue ()
483 return Value;
486 public override Constant Increment ()
488 return new CharConstant (checked ((char)(Value + 1)), loc);
491 public override bool IsDefaultValue {
492 get {
493 return Value == 0;
497 public override bool IsNegative {
498 get {
499 return false;
503 public override bool IsZeroInteger {
504 get { return Value == '\0'; }
507 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
509 if (target_type == TypeManager.byte_type) {
510 if (in_checked_context){
511 if (Value < Byte.MinValue || Value > Byte.MaxValue)
512 throw new OverflowException ();
514 return new ByteConstant ((byte) Value, Location);
516 if (target_type == TypeManager.sbyte_type) {
517 if (in_checked_context){
518 if (Value > SByte.MaxValue)
519 throw new OverflowException ();
521 return new SByteConstant ((sbyte) Value, Location);
523 if (target_type == TypeManager.short_type) {
524 if (in_checked_context){
525 if (Value > Int16.MaxValue)
526 throw new OverflowException ();
528 return new ShortConstant ((short) Value, Location);
530 if (target_type == TypeManager.int32_type)
531 return new IntConstant ((int) Value, Location);
532 if (target_type == TypeManager.uint32_type)
533 return new UIntConstant ((uint) Value, Location);
534 if (target_type == TypeManager.int64_type)
535 return new LongConstant ((long) Value, Location);
536 if (target_type == TypeManager.uint64_type)
537 return new ULongConstant ((ulong) Value, Location);
538 if (target_type == TypeManager.float_type)
539 return new FloatConstant ((float) Value, Location);
540 if (target_type == TypeManager.double_type)
541 return new DoubleConstant ((double) Value, Location);
542 if (target_type == TypeManager.decimal_type)
543 return new DecimalConstant ((decimal) Value, Location);
545 return null;
550 public class SByteConstant : IntegralConstant {
551 public readonly sbyte Value;
553 public SByteConstant (sbyte v, Location loc):
554 base (loc)
556 type = TypeManager.sbyte_type;
557 eclass = ExprClass.Value;
558 Value = v;
561 public override void Emit (EmitContext ec)
563 IntLiteral.EmitInt (ec.ig, Value);
566 public override string AsString ()
568 return Value.ToString ();
571 public override object GetValue ()
573 return Value;
576 public override Constant Increment ()
578 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
581 public override bool IsDefaultValue {
582 get {
583 return Value == 0;
587 public override bool IsNegative {
588 get {
589 return Value < 0;
593 public override bool IsZeroInteger {
594 get { return Value == 0; }
597 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
599 if (target_type == TypeManager.byte_type) {
600 if (in_checked_context && Value < 0)
601 throw new OverflowException ();
602 return new ByteConstant ((byte) Value, Location);
604 if (target_type == TypeManager.short_type)
605 return new ShortConstant ((short) Value, Location);
606 if (target_type == TypeManager.ushort_type) {
607 if (in_checked_context && Value < 0)
608 throw new OverflowException ();
609 return new UShortConstant ((ushort) Value, Location);
610 } if (target_type == TypeManager.int32_type)
611 return new IntConstant ((int) Value, Location);
612 if (target_type == TypeManager.uint32_type) {
613 if (in_checked_context && Value < 0)
614 throw new OverflowException ();
615 return new UIntConstant ((uint) Value, Location);
616 } if (target_type == TypeManager.int64_type)
617 return new LongConstant ((long) Value, Location);
618 if (target_type == TypeManager.uint64_type) {
619 if (in_checked_context && Value < 0)
620 throw new OverflowException ();
621 return new ULongConstant ((ulong) Value, Location);
623 if (target_type == TypeManager.float_type)
624 return new FloatConstant ((float) Value, Location);
625 if (target_type == TypeManager.double_type)
626 return new DoubleConstant ((double) Value, Location);
627 if (target_type == TypeManager.char_type) {
628 if (in_checked_context && Value < 0)
629 throw new OverflowException ();
630 return new CharConstant ((char) Value, Location);
632 if (target_type == TypeManager.decimal_type)
633 return new DecimalConstant ((decimal) Value, Location);
635 return null;
640 public class ShortConstant : IntegralConstant {
641 public readonly short Value;
643 public ShortConstant (short v, Location loc):
644 base (loc)
646 type = TypeManager.short_type;
647 eclass = ExprClass.Value;
648 Value = v;
651 public override void Emit (EmitContext ec)
653 IntLiteral.EmitInt (ec.ig, Value);
656 public override string AsString ()
658 return Value.ToString ();
661 public override object GetValue ()
663 return Value;
666 public override Constant Increment ()
668 return new ShortConstant (checked((short)(Value + 1)), loc);
671 public override bool IsDefaultValue {
672 get {
673 return Value == 0;
677 public override bool IsZeroInteger {
678 get { return Value == 0; }
681 public override bool IsNegative {
682 get {
683 return Value < 0;
687 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
689 if (target_type == TypeManager.byte_type) {
690 if (in_checked_context){
691 if (Value < Byte.MinValue || Value > Byte.MaxValue)
692 throw new OverflowException ();
694 return new ByteConstant ((byte) Value, Location);
696 if (target_type == TypeManager.sbyte_type) {
697 if (in_checked_context){
698 if (Value < SByte.MinValue || Value > SByte.MaxValue)
699 throw new OverflowException ();
701 return new SByteConstant ((sbyte) Value, Location);
703 if (target_type == TypeManager.ushort_type) {
704 if (in_checked_context && Value < 0)
705 throw new OverflowException ();
707 return new UShortConstant ((ushort) Value, Location);
709 if (target_type == TypeManager.int32_type)
710 return new IntConstant ((int) Value, Location);
711 if (target_type == TypeManager.uint32_type) {
712 if (in_checked_context && Value < 0)
713 throw new OverflowException ();
714 return new UIntConstant ((uint) Value, Location);
716 if (target_type == TypeManager.int64_type)
717 return new LongConstant ((long) Value, Location);
718 if (target_type == TypeManager.uint64_type) {
719 if (in_checked_context && Value < 0)
720 throw new OverflowException ();
721 return new ULongConstant ((ulong) Value, Location);
723 if (target_type == TypeManager.float_type)
724 return new FloatConstant ((float) Value, Location);
725 if (target_type == TypeManager.double_type)
726 return new DoubleConstant ((double) Value, Location);
727 if (target_type == TypeManager.char_type) {
728 if (in_checked_context){
729 if (Value < Char.MinValue)
730 throw new OverflowException ();
732 return new CharConstant ((char) Value, Location);
734 if (target_type == TypeManager.decimal_type)
735 return new DecimalConstant ((decimal) Value, Location);
737 return null;
742 public class UShortConstant : IntegralConstant {
743 public readonly ushort Value;
745 public UShortConstant (ushort v, Location loc):
746 base (loc)
748 type = TypeManager.ushort_type;
749 eclass = ExprClass.Value;
750 Value = v;
753 public override void Emit (EmitContext ec)
755 IntLiteral.EmitInt (ec.ig, Value);
758 public override string AsString ()
760 return Value.ToString ();
763 public override object GetValue ()
765 return Value;
768 public override Constant Increment ()
770 return new UShortConstant (checked((ushort)(Value + 1)), loc);
773 public override bool IsDefaultValue {
774 get {
775 return Value == 0;
779 public override bool IsNegative {
780 get {
781 return false;
785 public override bool IsZeroInteger {
786 get { return Value == 0; }
789 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
791 if (target_type == TypeManager.byte_type) {
792 if (in_checked_context){
793 if (Value > Byte.MaxValue)
794 throw new OverflowException ();
796 return new ByteConstant ((byte) Value, Location);
798 if (target_type == TypeManager.sbyte_type) {
799 if (in_checked_context){
800 if (Value > SByte.MaxValue)
801 throw new OverflowException ();
803 return new SByteConstant ((sbyte) Value, Location);
805 if (target_type == TypeManager.short_type) {
806 if (in_checked_context){
807 if (Value > Int16.MaxValue)
808 throw new OverflowException ();
810 return new ShortConstant ((short) Value, Location);
812 if (target_type == TypeManager.int32_type)
813 return new IntConstant ((int) Value, Location);
814 if (target_type == TypeManager.uint32_type)
815 return new UIntConstant ((uint) Value, Location);
816 if (target_type == TypeManager.int64_type)
817 return new LongConstant ((long) Value, Location);
818 if (target_type == TypeManager.uint64_type)
819 return new ULongConstant ((ulong) Value, Location);
820 if (target_type == TypeManager.float_type)
821 return new FloatConstant ((float) Value, Location);
822 if (target_type == TypeManager.double_type)
823 return new DoubleConstant ((double) Value, Location);
824 if (target_type == TypeManager.char_type) {
825 if (in_checked_context){
826 if (Value > Char.MaxValue)
827 throw new OverflowException ();
829 return new CharConstant ((char) Value, Location);
831 if (target_type == TypeManager.decimal_type)
832 return new DecimalConstant ((decimal) Value, Location);
834 return null;
838 public class IntConstant : IntegralConstant {
839 public readonly int Value;
841 public IntConstant (int v, Location loc):
842 base (loc)
844 type = TypeManager.int32_type;
845 eclass = ExprClass.Value;
846 Value = v;
849 static public void EmitInt (ILGenerator ig, int i)
851 switch (i){
852 case -1:
853 ig.Emit (OpCodes.Ldc_I4_M1);
854 break;
856 case 0:
857 ig.Emit (OpCodes.Ldc_I4_0);
858 break;
860 case 1:
861 ig.Emit (OpCodes.Ldc_I4_1);
862 break;
864 case 2:
865 ig.Emit (OpCodes.Ldc_I4_2);
866 break;
868 case 3:
869 ig.Emit (OpCodes.Ldc_I4_3);
870 break;
872 case 4:
873 ig.Emit (OpCodes.Ldc_I4_4);
874 break;
876 case 5:
877 ig.Emit (OpCodes.Ldc_I4_5);
878 break;
880 case 6:
881 ig.Emit (OpCodes.Ldc_I4_6);
882 break;
884 case 7:
885 ig.Emit (OpCodes.Ldc_I4_7);
886 break;
888 case 8:
889 ig.Emit (OpCodes.Ldc_I4_8);
890 break;
892 default:
893 if (i >= -128 && i <= 127){
894 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
895 } else
896 ig.Emit (OpCodes.Ldc_I4, i);
897 break;
901 public override void Emit (EmitContext ec)
903 EmitInt (ec.ig, Value);
906 public override string AsString ()
908 return Value.ToString ();
911 public override object GetValue ()
913 return Value;
916 public override Constant Increment ()
918 return new IntConstant (checked(Value + 1), loc);
921 public override bool IsDefaultValue {
922 get {
923 return Value == 0;
927 public override bool IsNegative {
928 get {
929 return Value < 0;
933 public override bool IsZeroInteger {
934 get { return Value == 0; }
937 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
939 if (target_type == TypeManager.byte_type) {
940 if (in_checked_context){
941 if (Value < Byte.MinValue || Value > Byte.MaxValue)
942 throw new OverflowException ();
944 return new ByteConstant ((byte) Value, Location);
946 if (target_type == TypeManager.sbyte_type) {
947 if (in_checked_context){
948 if (Value < SByte.MinValue || Value > SByte.MaxValue)
949 throw new OverflowException ();
951 return new SByteConstant ((sbyte) Value, Location);
953 if (target_type == TypeManager.short_type) {
954 if (in_checked_context){
955 if (Value < Int16.MinValue || Value > Int16.MaxValue)
956 throw new OverflowException ();
958 return new ShortConstant ((short) Value, Location);
960 if (target_type == TypeManager.ushort_type) {
961 if (in_checked_context){
962 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
963 throw new OverflowException ();
965 return new UShortConstant ((ushort) Value, Location);
967 if (target_type == TypeManager.uint32_type) {
968 if (in_checked_context){
969 if (Value < UInt32.MinValue)
970 throw new OverflowException ();
972 return new UIntConstant ((uint) Value, Location);
974 if (target_type == TypeManager.int64_type)
975 return new LongConstant ((long) Value, Location);
976 if (target_type == TypeManager.uint64_type) {
977 if (in_checked_context && Value < 0)
978 throw new OverflowException ();
979 return new ULongConstant ((ulong) Value, Location);
981 if (target_type == TypeManager.float_type)
982 return new FloatConstant ((float) Value, Location);
983 if (target_type == TypeManager.double_type)
984 return new DoubleConstant ((double) Value, Location);
985 if (target_type == TypeManager.char_type) {
986 if (in_checked_context){
987 if (Value < Char.MinValue || Value > Char.MaxValue)
988 throw new OverflowException ();
990 return new CharConstant ((char) Value, Location);
992 if (target_type == TypeManager.decimal_type)
993 return new DecimalConstant ((decimal) Value, Location);
995 return null;
998 public override Constant ConvertImplicitly (Type type)
1000 if (this.type == type)
1001 return this;
1003 Constant c = TryImplicitIntConversion (type);
1004 if (c != null)
1005 return c;
1007 return base.ConvertImplicitly (type);
1010 /// <summary>
1011 /// Attempts to perform an implicit constant conversion of the IntConstant
1012 /// into a different data type using casts (See Implicit Constant
1013 /// Expression Conversions)
1014 /// </summary>
1015 Constant TryImplicitIntConversion (Type target_type)
1017 if (target_type == TypeManager.sbyte_type) {
1018 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1019 return new SByteConstant ((sbyte) Value, loc);
1021 else if (target_type == TypeManager.byte_type) {
1022 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1023 return new ByteConstant ((byte) Value, loc);
1025 else if (target_type == TypeManager.short_type) {
1026 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1027 return new ShortConstant ((short) Value, loc);
1029 else if (target_type == TypeManager.ushort_type) {
1030 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1031 return new UShortConstant ((ushort) Value, loc);
1033 else if (target_type == TypeManager.uint32_type) {
1034 if (Value >= 0)
1035 return new UIntConstant ((uint) Value, loc);
1037 else if (target_type == TypeManager.uint64_type) {
1039 // we can optimize this case: a positive int32
1040 // always fits on a uint64. But we need an opcode
1041 // to do it.
1043 if (Value >= 0)
1044 return new ULongConstant ((ulong) Value, loc);
1046 else if (target_type == TypeManager.double_type)
1047 return new DoubleConstant ((double) Value, loc);
1048 else if (target_type == TypeManager.float_type)
1049 return new FloatConstant ((float) Value, loc);
1051 return null;
1055 public class UIntConstant : IntegralConstant {
1056 public readonly uint Value;
1058 public UIntConstant (uint v, Location loc):
1059 base (loc)
1061 type = TypeManager.uint32_type;
1062 eclass = ExprClass.Value;
1063 Value = v;
1066 public override void Emit (EmitContext ec)
1068 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1071 public override string AsString ()
1073 return Value.ToString ();
1076 public override object GetValue ()
1078 return Value;
1081 public override Constant Increment ()
1083 return new UIntConstant (checked(Value + 1), loc);
1086 public override bool IsDefaultValue {
1087 get {
1088 return Value == 0;
1092 public override bool IsNegative {
1093 get {
1094 return false;
1098 public override bool IsZeroInteger {
1099 get { return Value == 0; }
1102 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1104 if (target_type == TypeManager.byte_type) {
1105 if (in_checked_context){
1106 if (Value < Char.MinValue || Value > Char.MaxValue)
1107 throw new OverflowException ();
1109 return new ByteConstant ((byte) Value, Location);
1111 if (target_type == TypeManager.sbyte_type) {
1112 if (in_checked_context){
1113 if (Value > SByte.MaxValue)
1114 throw new OverflowException ();
1116 return new SByteConstant ((sbyte) Value, Location);
1118 if (target_type == TypeManager.short_type) {
1119 if (in_checked_context){
1120 if (Value > Int16.MaxValue)
1121 throw new OverflowException ();
1123 return new ShortConstant ((short) Value, Location);
1125 if (target_type == TypeManager.ushort_type) {
1126 if (in_checked_context){
1127 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1128 throw new OverflowException ();
1130 return new UShortConstant ((ushort) Value, Location);
1132 if (target_type == TypeManager.int32_type) {
1133 if (in_checked_context){
1134 if (Value > Int32.MaxValue)
1135 throw new OverflowException ();
1137 return new IntConstant ((int) Value, Location);
1139 if (target_type == TypeManager.int64_type)
1140 return new LongConstant ((long) Value, Location);
1141 if (target_type == TypeManager.uint64_type)
1142 return new ULongConstant ((ulong) Value, Location);
1143 if (target_type == TypeManager.float_type)
1144 return new FloatConstant ((float) Value, Location);
1145 if (target_type == TypeManager.double_type)
1146 return new DoubleConstant ((double) Value, Location);
1147 if (target_type == TypeManager.char_type) {
1148 if (in_checked_context){
1149 if (Value < Char.MinValue || Value > Char.MaxValue)
1150 throw new OverflowException ();
1152 return new CharConstant ((char) Value, Location);
1154 if (target_type == TypeManager.decimal_type)
1155 return new DecimalConstant ((decimal) Value, Location);
1157 return null;
1162 public class LongConstant : IntegralConstant {
1163 public readonly long Value;
1165 public LongConstant (long v, Location loc):
1166 base (loc)
1168 type = TypeManager.int64_type;
1169 eclass = ExprClass.Value;
1170 Value = v;
1173 public override void Emit (EmitContext ec)
1175 EmitLong (ec.ig, Value);
1178 static public void EmitLong (ILGenerator ig, long l)
1180 if (l >= int.MinValue && l <= int.MaxValue) {
1181 IntLiteral.EmitInt (ig, unchecked ((int) l));
1182 ig.Emit (OpCodes.Conv_I8);
1183 return;
1186 if (l >= 0 && l <= uint.MaxValue) {
1187 IntLiteral.EmitInt (ig, unchecked ((int) l));
1188 ig.Emit (OpCodes.Conv_U8);
1189 return;
1192 ig.Emit (OpCodes.Ldc_I8, l);
1195 public override string AsString ()
1197 return Value.ToString ();
1200 public override object GetValue ()
1202 return Value;
1205 public override Constant Increment ()
1207 return new LongConstant (checked(Value + 1), loc);
1210 public override bool IsDefaultValue {
1211 get {
1212 return Value == 0;
1216 public override bool IsNegative {
1217 get {
1218 return Value < 0;
1222 public override bool IsZeroInteger {
1223 get { return Value == 0; }
1226 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1228 if (target_type == TypeManager.byte_type) {
1229 if (in_checked_context){
1230 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1231 throw new OverflowException ();
1233 return new ByteConstant ((byte) Value, Location);
1235 if (target_type == TypeManager.sbyte_type) {
1236 if (in_checked_context){
1237 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1238 throw new OverflowException ();
1240 return new SByteConstant ((sbyte) Value, Location);
1242 if (target_type == TypeManager.short_type) {
1243 if (in_checked_context){
1244 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1245 throw new OverflowException ();
1247 return new ShortConstant ((short) Value, Location);
1249 if (target_type == TypeManager.ushort_type) {
1250 if (in_checked_context){
1251 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1252 throw new OverflowException ();
1254 return new UShortConstant ((ushort) Value, Location);
1256 if (target_type == TypeManager.int32_type) {
1257 if (in_checked_context){
1258 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1259 throw new OverflowException ();
1261 return new IntConstant ((int) Value, Location);
1263 if (target_type == TypeManager.uint32_type) {
1264 if (in_checked_context){
1265 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1266 throw new OverflowException ();
1268 return new UIntConstant ((uint) Value, Location);
1270 if (target_type == TypeManager.uint64_type) {
1271 if (in_checked_context && Value < 0)
1272 throw new OverflowException ();
1273 return new ULongConstant ((ulong) Value, Location);
1275 if (target_type == TypeManager.float_type)
1276 return new FloatConstant ((float) Value, Location);
1277 if (target_type == TypeManager.double_type)
1278 return new DoubleConstant ((double) Value, Location);
1279 if (target_type == TypeManager.char_type) {
1280 if (in_checked_context){
1281 if (Value < Char.MinValue || Value > Char.MaxValue)
1282 throw new OverflowException ();
1284 return new CharConstant ((char) Value, Location);
1286 if (target_type == TypeManager.decimal_type)
1287 return new DecimalConstant ((decimal) Value, Location);
1289 return null;
1292 public override Constant ConvertImplicitly (Type type)
1294 if (Value >= 0 && type == TypeManager.uint64_type) {
1295 return new ULongConstant ((ulong) Value, loc);
1298 return base.ConvertImplicitly (type);
1302 public class ULongConstant : IntegralConstant {
1303 public readonly ulong Value;
1305 public ULongConstant (ulong v, Location loc):
1306 base (loc)
1308 type = TypeManager.uint64_type;
1309 eclass = ExprClass.Value;
1310 Value = v;
1313 public override void Emit (EmitContext ec)
1315 ILGenerator ig = ec.ig;
1317 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1320 public override string AsString ()
1322 return Value.ToString ();
1325 public override object GetValue ()
1327 return Value;
1330 public override Constant Increment ()
1332 return new ULongConstant (checked(Value + 1), loc);
1335 public override bool IsDefaultValue {
1336 get {
1337 return Value == 0;
1341 public override bool IsNegative {
1342 get {
1343 return false;
1347 public override bool IsZeroInteger {
1348 get { return Value == 0; }
1351 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1353 if (target_type == TypeManager.byte_type) {
1354 if (in_checked_context && Value > Byte.MaxValue)
1355 throw new OverflowException ();
1356 return new ByteConstant ((byte) Value, Location);
1358 if (target_type == TypeManager.sbyte_type) {
1359 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1360 throw new OverflowException ();
1361 return new SByteConstant ((sbyte) Value, Location);
1363 if (target_type == TypeManager.short_type) {
1364 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1365 throw new OverflowException ();
1366 return new ShortConstant ((short) Value, Location);
1368 if (target_type == TypeManager.ushort_type) {
1369 if (in_checked_context && Value > UInt16.MaxValue)
1370 throw new OverflowException ();
1371 return new UShortConstant ((ushort) Value, Location);
1373 if (target_type == TypeManager.int32_type) {
1374 if (in_checked_context && Value > UInt32.MaxValue)
1375 throw new OverflowException ();
1376 return new IntConstant ((int) Value, Location);
1378 if (target_type == TypeManager.uint32_type) {
1379 if (in_checked_context && Value > UInt32.MaxValue)
1380 throw new OverflowException ();
1381 return new UIntConstant ((uint) Value, Location);
1383 if (target_type == TypeManager.int64_type) {
1384 if (in_checked_context && Value > Int64.MaxValue)
1385 throw new OverflowException ();
1386 return new LongConstant ((long) Value, Location);
1388 if (target_type == TypeManager.float_type)
1389 return new FloatConstant ((float) Value, Location);
1390 if (target_type == TypeManager.double_type)
1391 return new DoubleConstant ((double) Value, Location);
1392 if (target_type == TypeManager.char_type) {
1393 if (in_checked_context && Value > Char.MaxValue)
1394 throw new OverflowException ();
1395 return new CharConstant ((char) Value, Location);
1397 if (target_type == TypeManager.decimal_type)
1398 return new DecimalConstant ((decimal) Value, Location);
1400 return null;
1405 public class FloatConstant : Constant {
1406 public float Value;
1408 public FloatConstant (float v, Location loc):
1409 base (loc)
1411 type = TypeManager.float_type;
1412 eclass = ExprClass.Value;
1413 Value = v;
1416 public override void Emit (EmitContext ec)
1418 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1421 public override string AsString ()
1423 return Value.ToString ();
1426 public override object GetValue ()
1428 return Value;
1431 public override Constant Increment ()
1433 return new FloatConstant (checked(Value + 1), loc);
1436 public override bool IsDefaultValue {
1437 get {
1438 return Value == 0;
1442 public override bool IsNegative {
1443 get {
1444 return Value < 0;
1448 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1450 if (target_type == TypeManager.byte_type) {
1451 if (in_checked_context){
1452 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1453 throw new OverflowException ();
1455 return new ByteConstant ((byte) Value, Location);
1457 if (target_type == TypeManager.sbyte_type) {
1458 if (in_checked_context){
1459 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1460 throw new OverflowException ();
1462 return new SByteConstant ((sbyte) Value, Location);
1464 if (target_type == TypeManager.short_type) {
1465 if (in_checked_context){
1466 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1467 throw new OverflowException ();
1469 return new ShortConstant ((short) Value, Location);
1471 if (target_type == TypeManager.ushort_type) {
1472 if (in_checked_context){
1473 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1474 throw new OverflowException ();
1476 return new UShortConstant ((ushort) Value, Location);
1478 if (target_type == TypeManager.int32_type) {
1479 if (in_checked_context){
1480 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1481 throw new OverflowException ();
1483 return new IntConstant ((int) Value, Location);
1485 if (target_type == TypeManager.uint32_type) {
1486 if (in_checked_context){
1487 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1488 throw new OverflowException ();
1490 return new UIntConstant ((uint) Value, Location);
1492 if (target_type == TypeManager.int64_type) {
1493 if (in_checked_context){
1494 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1495 throw new OverflowException ();
1497 return new LongConstant ((long) Value, Location);
1499 if (target_type == TypeManager.uint64_type) {
1500 if (in_checked_context){
1501 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1502 throw new OverflowException ();
1504 return new ULongConstant ((ulong) Value, Location);
1506 if (target_type == TypeManager.double_type)
1507 return new DoubleConstant ((double) Value, Location);
1508 if (target_type == TypeManager.char_type) {
1509 if (in_checked_context){
1510 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1511 throw new OverflowException ();
1513 return new CharConstant ((char) Value, Location);
1515 if (target_type == TypeManager.decimal_type)
1516 return new DecimalConstant ((decimal) Value, Location);
1518 return null;
1523 public class DoubleConstant : Constant {
1524 public double Value;
1526 public DoubleConstant (double v, Location loc):
1527 base (loc)
1529 type = TypeManager.double_type;
1530 eclass = ExprClass.Value;
1531 Value = v;
1534 public override void Emit (EmitContext ec)
1536 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1539 public override string AsString ()
1541 return Value.ToString ();
1544 public override object GetValue ()
1546 return Value;
1549 public override Constant Increment ()
1551 return new DoubleConstant (checked(Value + 1), loc);
1554 public override bool IsDefaultValue {
1555 get {
1556 return Value == 0;
1560 public override bool IsNegative {
1561 get {
1562 return Value < 0;
1566 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1568 if (target_type == TypeManager.byte_type) {
1569 if (in_checked_context){
1570 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1571 throw new OverflowException ();
1573 return new ByteConstant ((byte) Value, Location);
1575 if (target_type == TypeManager.sbyte_type) {
1576 if (in_checked_context){
1577 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1578 throw new OverflowException ();
1580 return new SByteConstant ((sbyte) Value, Location);
1582 if (target_type == TypeManager.short_type) {
1583 if (in_checked_context){
1584 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1585 throw new OverflowException ();
1587 return new ShortConstant ((short) Value, Location);
1589 if (target_type == TypeManager.ushort_type) {
1590 if (in_checked_context){
1591 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1592 throw new OverflowException ();
1594 return new UShortConstant ((ushort) Value, Location);
1596 if (target_type == TypeManager.int32_type) {
1597 if (in_checked_context){
1598 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1599 throw new OverflowException ();
1601 return new IntConstant ((int) Value, Location);
1603 if (target_type == TypeManager.uint32_type) {
1604 if (in_checked_context){
1605 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1606 throw new OverflowException ();
1608 return new UIntConstant ((uint) Value, Location);
1610 if (target_type == TypeManager.int64_type) {
1611 if (in_checked_context){
1612 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1613 throw new OverflowException ();
1615 return new LongConstant ((long) Value, Location);
1617 if (target_type == TypeManager.uint64_type) {
1618 if (in_checked_context){
1619 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1620 throw new OverflowException ();
1622 return new ULongConstant ((ulong) Value, Location);
1624 if (target_type == TypeManager.float_type)
1625 return new FloatConstant ((float) Value, Location);
1626 if (target_type == TypeManager.char_type) {
1627 if (in_checked_context){
1628 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1629 throw new OverflowException ();
1631 return new CharConstant ((char) Value, Location);
1633 if (target_type == TypeManager.decimal_type)
1634 return new DecimalConstant ((decimal) Value, Location);
1636 return null;
1641 public class DecimalConstant : Constant {
1642 public readonly decimal Value;
1644 public DecimalConstant (decimal d, Location loc):
1645 base (loc)
1647 type = TypeManager.decimal_type;
1648 eclass = ExprClass.Value;
1649 Value = d;
1652 override public string AsString ()
1654 return Value.ToString () + "M";
1657 public override object GetValue ()
1659 return (object) Value;
1662 public override void Emit (EmitContext ec)
1664 ILGenerator ig = ec.ig;
1666 int [] words = Decimal.GetBits (Value);
1667 int power = (words [3] >> 16) & 0xff;
1669 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1671 if (TypeManager.void_decimal_ctor_int_arg == null) {
1672 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1673 TypeManager.decimal_type, loc, TypeManager.int32_type);
1675 if (TypeManager.void_decimal_ctor_int_arg == null)
1676 return;
1679 IntConstant.EmitInt (ig, (int)Value);
1680 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1681 return;
1686 // FIXME: we could optimize this, and call a better
1687 // constructor
1690 IntConstant.EmitInt (ig, words [0]);
1691 IntConstant.EmitInt (ig, words [1]);
1692 IntConstant.EmitInt (ig, words [2]);
1694 // sign
1695 IntConstant.EmitInt (ig, words [3] >> 31);
1697 // power
1698 IntConstant.EmitInt (ig, power);
1700 if (TypeManager.void_decimal_ctor_five_args == null) {
1701 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1702 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1703 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1705 if (TypeManager.void_decimal_ctor_five_args == null)
1706 return;
1709 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1712 public override Constant Increment ()
1714 return new DecimalConstant (checked (Value + 1), loc);
1717 public override bool IsDefaultValue {
1718 get {
1719 return Value == 0;
1723 public override bool IsNegative {
1724 get {
1725 return Value < 0;
1729 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1731 if (target_type == TypeManager.sbyte_type)
1732 return new SByteConstant ((sbyte)Value, loc);
1733 if (target_type == TypeManager.byte_type)
1734 return new ByteConstant ((byte)Value, loc);
1735 if (target_type == TypeManager.short_type)
1736 return new ShortConstant ((short)Value, loc);
1737 if (target_type == TypeManager.ushort_type)
1738 return new UShortConstant ((ushort)Value, loc);
1739 if (target_type == TypeManager.int32_type)
1740 return new IntConstant ((int)Value, loc);
1741 if (target_type == TypeManager.uint32_type)
1742 return new UIntConstant ((uint)Value, loc);
1743 if (target_type == TypeManager.int64_type)
1744 return new LongConstant ((long)Value, loc);
1745 if (target_type == TypeManager.uint64_type)
1746 return new ULongConstant ((ulong)Value, loc);
1747 if (target_type == TypeManager.char_type)
1748 return new CharConstant ((char)Value, loc);
1749 if (target_type == TypeManager.float_type)
1750 return new FloatConstant ((float)Value, loc);
1751 if (target_type == TypeManager.double_type)
1752 return new DoubleConstant ((double)Value, loc);
1754 return null;
1759 public class StringConstant : Constant {
1760 public readonly string Value;
1762 public StringConstant (string s, Location loc):
1763 base (loc)
1765 type = TypeManager.string_type;
1766 eclass = ExprClass.Value;
1767 Value = s;
1770 // FIXME: Escape the string.
1771 override public string AsString ()
1773 return "\"" + Value + "\"";
1776 public override object GetValue ()
1778 return Value;
1781 public override void Emit (EmitContext ec)
1783 if (Value == null) {
1784 ec.ig.Emit (OpCodes.Ldnull);
1785 return;
1789 // Use string.Empty for both literals and constants even if
1790 // it's not allowed at language level
1792 if (Value.Length == 0 && RootContext.Optimize && ec.TypeContainer.TypeBuilder != TypeManager.string_type) {
1793 if (TypeManager.string_empty == null)
1794 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
1796 if (TypeManager.string_empty != null) {
1797 ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1798 return;
1802 ec.ig.Emit (OpCodes.Ldstr, Value);
1805 public override Constant Increment ()
1807 throw new NotSupportedException ();
1810 public override bool IsDefaultValue {
1811 get {
1812 return Value == null;
1816 public override bool IsNegative {
1817 get {
1818 return false;
1822 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1824 return null;
1828 /// <summary>
1829 /// The value is constant, but when emitted has a side effect. This is
1830 /// used by BitwiseAnd to ensure that the second expression is invoked
1831 /// regardless of the value of the left side.
1832 /// </summary>
1834 public class SideEffectConstant : Constant {
1835 public Constant value;
1836 Expression side_effect;
1838 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
1840 this.value = value;
1841 while (side_effect is SideEffectConstant)
1842 side_effect = ((SideEffectConstant) side_effect).side_effect;
1843 this.side_effect = side_effect;
1844 eclass = ExprClass.Value;
1845 type = value.Type;
1848 public override string AsString ()
1850 return value.AsString ();
1853 public override object GetValue ()
1855 return value.GetValue ();
1858 public override void Emit (EmitContext ec)
1860 side_effect.EmitSideEffect (ec);
1861 value.Emit (ec);
1864 public override void EmitSideEffect (EmitContext ec)
1866 side_effect.EmitSideEffect (ec);
1867 value.EmitSideEffect (ec);
1870 public override bool IsDefaultValue {
1871 get { return value.IsDefaultValue; }
1874 public override Constant Increment ()
1876 throw new NotSupportedException ();
1879 public override bool IsNegative {
1880 get { return value.IsNegative; }
1883 public override bool IsZeroInteger {
1884 get { return value.IsZeroInteger; }
1887 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1889 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
1890 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);