2009-11-15 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / constant.cs
blobc59a1ff1544f70316f3a3f868bd27c9c11ef2e3d
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 (ResolveContext 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 (ResolveContext ec)
76 return this;
79 public override void Error_ValueCannotBeConverted (ResolveContext 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 ec.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 (ResolveContext 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) {
158 if (TypeManager.IsNullableType (t))
159 return Nullable.LiftedNull.Create (t, loc);
161 if (TypeManager.IsReferenceType (t))
162 return new NullConstant (t, loc);
165 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
166 v, TypeManager.CSharpName (t));
169 public override Expression CreateExpressionTree (ResolveContext ec)
171 Arguments args = new Arguments (2);
172 args.Add (new Argument (this));
173 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
175 return CreateExpressionFactoryCall (ec, "Constant", args);
179 /// <summary>
180 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
181 /// It throws OverflowException
182 /// </summary>
183 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
184 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
186 /// <summary>
187 /// Attempts to do a compile-time folding of a constant cast.
188 /// </summary>
189 public Constant TryReduce (ResolveContext ec, Type target_type, Location loc)
191 try {
192 return TryReduce (ec, target_type);
194 catch (OverflowException) {
195 if (ec.ConstantCheckState) {
196 ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
197 GetValue ().ToString (), TypeManager.CSharpName (target_type));
198 } else {
199 Error_ValueCannotBeConverted (ec, loc, target_type, false);
202 return New.Constantify (target_type);
206 Constant TryReduce (ResolveContext ec, Type target_type)
208 if (Type == target_type)
209 return this;
211 if (TypeManager.IsEnumType (target_type)) {
212 Constant c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type));
213 if (c == null)
214 return null;
216 return new EnumConstant (c, target_type);
219 return ConvertExplicitly (ec.ConstantCheckState, target_type);
222 public abstract Constant Increment ();
224 /// <summary>
225 /// Need to pass type as the constant can require a boxing
226 /// and in such case no optimization is possible
227 /// </summary>
228 public bool IsDefaultInitializer (Type type)
230 if (type == Type)
231 return IsDefaultValue;
233 return this is NullLiteral;
236 public abstract bool IsDefaultValue {
237 get;
240 public abstract bool IsNegative {
241 get;
245 // When constant is declared as literal
247 public virtual bool IsLiteral {
248 get { return false; }
252 // Returns true iff 1) the stack type of this is one of Object,
253 // int32, int64 and 2) this == 0 or this == null.
255 public virtual bool IsZeroInteger {
256 get { return false; }
259 public override void EmitSideEffect (EmitContext ec)
261 // do nothing
264 protected override void CloneTo (CloneContext clonectx, Expression target)
266 // CloneTo: Nothing, we do not keep any state on this expression
269 #if NET_4_0
270 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
272 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type);
274 #endif
276 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
278 // A constant cannot be of generic type
282 public abstract class IntegralConstant : Constant {
283 protected IntegralConstant (Location loc) :
284 base (loc)
288 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
290 try {
291 ConvertExplicitly (true, target);
292 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
294 catch
296 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
297 GetValue ().ToString (), TypeManager.CSharpName (target));
302 public class BoolConstant : Constant {
303 public readonly bool Value;
305 public BoolConstant (bool val, Location loc):
306 base (loc)
308 type = TypeManager.bool_type;
309 eclass = ExprClass.Value;
311 Value = val;
314 override public string AsString ()
316 return Value ? "true" : "false";
319 public override object GetValue ()
321 return (object) Value;
325 public override void Emit (EmitContext ec)
327 if (Value)
328 ec.ig.Emit (OpCodes.Ldc_I4_1);
329 else
330 ec.ig.Emit (OpCodes.Ldc_I4_0);
333 public override Constant Increment ()
335 throw new NotSupportedException ();
338 public override bool IsDefaultValue {
339 get {
340 return !Value;
344 public override bool IsNegative {
345 get {
346 return false;
350 public override bool IsZeroInteger {
351 get { return Value == false; }
354 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
356 return null;
361 public class ByteConstant : IntegralConstant {
362 public readonly byte Value;
364 public ByteConstant (byte v, Location loc):
365 base (loc)
367 type = TypeManager.byte_type;
368 eclass = ExprClass.Value;
369 Value = v;
372 public override void Emit (EmitContext ec)
374 IntLiteral.EmitInt (ec.ig, Value);
377 public override string AsString ()
379 return Value.ToString ();
382 public override object GetValue ()
384 return Value;
387 public override Constant Increment ()
389 return new ByteConstant (checked ((byte)(Value + 1)), loc);
392 public override bool IsDefaultValue {
393 get {
394 return Value == 0;
398 public override bool IsNegative {
399 get {
400 return false;
404 public override bool IsZeroInteger {
405 get { return Value == 0; }
408 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
410 if (target_type == TypeManager.sbyte_type) {
411 if (in_checked_context){
412 if (Value > SByte.MaxValue)
413 throw new OverflowException ();
415 return new SByteConstant ((sbyte) Value, Location);
417 if (target_type == TypeManager.short_type)
418 return new ShortConstant ((short) Value, Location);
419 if (target_type == TypeManager.ushort_type)
420 return new UShortConstant ((ushort) Value, Location);
421 if (target_type == TypeManager.int32_type)
422 return new IntConstant ((int) Value, Location);
423 if (target_type == TypeManager.uint32_type)
424 return new UIntConstant ((uint) Value, Location);
425 if (target_type == TypeManager.int64_type)
426 return new LongConstant ((long) Value, Location);
427 if (target_type == TypeManager.uint64_type)
428 return new ULongConstant ((ulong) Value, Location);
429 if (target_type == TypeManager.float_type)
430 return new FloatConstant ((float) Value, Location);
431 if (target_type == TypeManager.double_type)
432 return new DoubleConstant ((double) Value, Location);
433 if (target_type == TypeManager.char_type)
434 return new CharConstant ((char) Value, Location);
435 if (target_type == TypeManager.decimal_type)
436 return new DecimalConstant ((decimal) Value, Location);
438 return null;
443 public class CharConstant : Constant {
444 public readonly char Value;
446 public CharConstant (char v, Location loc):
447 base (loc)
449 type = TypeManager.char_type;
450 eclass = ExprClass.Value;
451 Value = v;
454 public override void Emit (EmitContext ec)
456 IntLiteral.EmitInt (ec.ig, Value);
459 static public string descape (char c)
461 switch (c){
462 case '\a':
463 return "\\a";
464 case '\b':
465 return "\\b";
466 case '\n':
467 return "\\n";
468 case '\t':
469 return "\\t";
470 case '\v':
471 return "\\v";
472 case '\r':
473 return "\\r";
474 case '\\':
475 return "\\\\";
476 case '\f':
477 return "\\f";
478 case '\0':
479 return "\\0";
480 case '"':
481 return "\\\"";
482 case '\'':
483 return "\\\'";
485 return c.ToString ();
488 public override string AsString ()
490 return "\"" + descape (Value) + "\"";
493 public override object GetValue ()
495 return Value;
498 public override Constant Increment ()
500 return new CharConstant (checked ((char)(Value + 1)), loc);
503 public override bool IsDefaultValue {
504 get {
505 return Value == 0;
509 public override bool IsNegative {
510 get {
511 return false;
515 public override bool IsZeroInteger {
516 get { return Value == '\0'; }
519 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
521 if (target_type == TypeManager.byte_type) {
522 if (in_checked_context){
523 if (Value < Byte.MinValue || Value > Byte.MaxValue)
524 throw new OverflowException ();
526 return new ByteConstant ((byte) Value, Location);
528 if (target_type == TypeManager.sbyte_type) {
529 if (in_checked_context){
530 if (Value > SByte.MaxValue)
531 throw new OverflowException ();
533 return new SByteConstant ((sbyte) Value, Location);
535 if (target_type == TypeManager.short_type) {
536 if (in_checked_context){
537 if (Value > Int16.MaxValue)
538 throw new OverflowException ();
540 return new ShortConstant ((short) Value, Location);
542 if (target_type == TypeManager.int32_type)
543 return new IntConstant ((int) Value, Location);
544 if (target_type == TypeManager.uint32_type)
545 return new UIntConstant ((uint) Value, Location);
546 if (target_type == TypeManager.int64_type)
547 return new LongConstant ((long) Value, Location);
548 if (target_type == TypeManager.uint64_type)
549 return new ULongConstant ((ulong) Value, Location);
550 if (target_type == TypeManager.float_type)
551 return new FloatConstant ((float) Value, Location);
552 if (target_type == TypeManager.double_type)
553 return new DoubleConstant ((double) Value, Location);
554 if (target_type == TypeManager.decimal_type)
555 return new DecimalConstant ((decimal) Value, Location);
557 return null;
562 public class SByteConstant : IntegralConstant {
563 public readonly sbyte Value;
565 public SByteConstant (sbyte v, Location loc):
566 base (loc)
568 type = TypeManager.sbyte_type;
569 eclass = ExprClass.Value;
570 Value = v;
573 public override void Emit (EmitContext ec)
575 IntLiteral.EmitInt (ec.ig, Value);
578 public override string AsString ()
580 return Value.ToString ();
583 public override object GetValue ()
585 return Value;
588 public override Constant Increment ()
590 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
593 public override bool IsDefaultValue {
594 get {
595 return Value == 0;
599 public override bool IsNegative {
600 get {
601 return Value < 0;
605 public override bool IsZeroInteger {
606 get { return Value == 0; }
609 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
611 if (target_type == TypeManager.byte_type) {
612 if (in_checked_context && Value < 0)
613 throw new OverflowException ();
614 return new ByteConstant ((byte) Value, Location);
616 if (target_type == TypeManager.short_type)
617 return new ShortConstant ((short) Value, Location);
618 if (target_type == TypeManager.ushort_type) {
619 if (in_checked_context && Value < 0)
620 throw new OverflowException ();
621 return new UShortConstant ((ushort) Value, Location);
622 } if (target_type == TypeManager.int32_type)
623 return new IntConstant ((int) Value, Location);
624 if (target_type == TypeManager.uint32_type) {
625 if (in_checked_context && Value < 0)
626 throw new OverflowException ();
627 return new UIntConstant ((uint) Value, Location);
628 } if (target_type == TypeManager.int64_type)
629 return new LongConstant ((long) Value, Location);
630 if (target_type == TypeManager.uint64_type) {
631 if (in_checked_context && Value < 0)
632 throw new OverflowException ();
633 return new ULongConstant ((ulong) Value, Location);
635 if (target_type == TypeManager.float_type)
636 return new FloatConstant ((float) Value, Location);
637 if (target_type == TypeManager.double_type)
638 return new DoubleConstant ((double) Value, Location);
639 if (target_type == TypeManager.char_type) {
640 if (in_checked_context && Value < 0)
641 throw new OverflowException ();
642 return new CharConstant ((char) Value, Location);
644 if (target_type == TypeManager.decimal_type)
645 return new DecimalConstant ((decimal) Value, Location);
647 return null;
652 public class ShortConstant : IntegralConstant {
653 public readonly short Value;
655 public ShortConstant (short v, Location loc):
656 base (loc)
658 type = TypeManager.short_type;
659 eclass = ExprClass.Value;
660 Value = v;
663 public override void Emit (EmitContext ec)
665 IntLiteral.EmitInt (ec.ig, Value);
668 public override string AsString ()
670 return Value.ToString ();
673 public override object GetValue ()
675 return Value;
678 public override Constant Increment ()
680 return new ShortConstant (checked((short)(Value + 1)), loc);
683 public override bool IsDefaultValue {
684 get {
685 return Value == 0;
689 public override bool IsZeroInteger {
690 get { return Value == 0; }
693 public override bool IsNegative {
694 get {
695 return Value < 0;
699 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
701 if (target_type == TypeManager.byte_type) {
702 if (in_checked_context){
703 if (Value < Byte.MinValue || Value > Byte.MaxValue)
704 throw new OverflowException ();
706 return new ByteConstant ((byte) Value, Location);
708 if (target_type == TypeManager.sbyte_type) {
709 if (in_checked_context){
710 if (Value < SByte.MinValue || Value > SByte.MaxValue)
711 throw new OverflowException ();
713 return new SByteConstant ((sbyte) Value, Location);
715 if (target_type == TypeManager.ushort_type) {
716 if (in_checked_context && Value < 0)
717 throw new OverflowException ();
719 return new UShortConstant ((ushort) Value, Location);
721 if (target_type == TypeManager.int32_type)
722 return new IntConstant ((int) Value, Location);
723 if (target_type == TypeManager.uint32_type) {
724 if (in_checked_context && Value < 0)
725 throw new OverflowException ();
726 return new UIntConstant ((uint) Value, Location);
728 if (target_type == TypeManager.int64_type)
729 return new LongConstant ((long) Value, Location);
730 if (target_type == TypeManager.uint64_type) {
731 if (in_checked_context && Value < 0)
732 throw new OverflowException ();
733 return new ULongConstant ((ulong) Value, Location);
735 if (target_type == TypeManager.float_type)
736 return new FloatConstant ((float) Value, Location);
737 if (target_type == TypeManager.double_type)
738 return new DoubleConstant ((double) Value, Location);
739 if (target_type == TypeManager.char_type) {
740 if (in_checked_context){
741 if (Value < Char.MinValue)
742 throw new OverflowException ();
744 return new CharConstant ((char) Value, Location);
746 if (target_type == TypeManager.decimal_type)
747 return new DecimalConstant ((decimal) Value, Location);
749 return null;
754 public class UShortConstant : IntegralConstant {
755 public readonly ushort Value;
757 public UShortConstant (ushort v, Location loc):
758 base (loc)
760 type = TypeManager.ushort_type;
761 eclass = ExprClass.Value;
762 Value = v;
765 public override void Emit (EmitContext ec)
767 IntLiteral.EmitInt (ec.ig, Value);
770 public override string AsString ()
772 return Value.ToString ();
775 public override object GetValue ()
777 return Value;
780 public override Constant Increment ()
782 return new UShortConstant (checked((ushort)(Value + 1)), loc);
785 public override bool IsDefaultValue {
786 get {
787 return Value == 0;
791 public override bool IsNegative {
792 get {
793 return false;
797 public override bool IsZeroInteger {
798 get { return Value == 0; }
801 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
803 if (target_type == TypeManager.byte_type) {
804 if (in_checked_context){
805 if (Value > Byte.MaxValue)
806 throw new OverflowException ();
808 return new ByteConstant ((byte) Value, Location);
810 if (target_type == TypeManager.sbyte_type) {
811 if (in_checked_context){
812 if (Value > SByte.MaxValue)
813 throw new OverflowException ();
815 return new SByteConstant ((sbyte) Value, Location);
817 if (target_type == TypeManager.short_type) {
818 if (in_checked_context){
819 if (Value > Int16.MaxValue)
820 throw new OverflowException ();
822 return new ShortConstant ((short) Value, Location);
824 if (target_type == TypeManager.int32_type)
825 return new IntConstant ((int) Value, Location);
826 if (target_type == TypeManager.uint32_type)
827 return new UIntConstant ((uint) Value, Location);
828 if (target_type == TypeManager.int64_type)
829 return new LongConstant ((long) Value, Location);
830 if (target_type == TypeManager.uint64_type)
831 return new ULongConstant ((ulong) Value, Location);
832 if (target_type == TypeManager.float_type)
833 return new FloatConstant ((float) Value, Location);
834 if (target_type == TypeManager.double_type)
835 return new DoubleConstant ((double) Value, Location);
836 if (target_type == TypeManager.char_type) {
837 if (in_checked_context){
838 if (Value > Char.MaxValue)
839 throw new OverflowException ();
841 return new CharConstant ((char) Value, Location);
843 if (target_type == TypeManager.decimal_type)
844 return new DecimalConstant ((decimal) Value, Location);
846 return null;
850 public class IntConstant : IntegralConstant {
851 public readonly int Value;
853 public IntConstant (int v, Location loc):
854 base (loc)
856 type = TypeManager.int32_type;
857 eclass = ExprClass.Value;
858 Value = v;
861 static public void EmitInt (ILGenerator ig, int i)
863 switch (i){
864 case -1:
865 ig.Emit (OpCodes.Ldc_I4_M1);
866 break;
868 case 0:
869 ig.Emit (OpCodes.Ldc_I4_0);
870 break;
872 case 1:
873 ig.Emit (OpCodes.Ldc_I4_1);
874 break;
876 case 2:
877 ig.Emit (OpCodes.Ldc_I4_2);
878 break;
880 case 3:
881 ig.Emit (OpCodes.Ldc_I4_3);
882 break;
884 case 4:
885 ig.Emit (OpCodes.Ldc_I4_4);
886 break;
888 case 5:
889 ig.Emit (OpCodes.Ldc_I4_5);
890 break;
892 case 6:
893 ig.Emit (OpCodes.Ldc_I4_6);
894 break;
896 case 7:
897 ig.Emit (OpCodes.Ldc_I4_7);
898 break;
900 case 8:
901 ig.Emit (OpCodes.Ldc_I4_8);
902 break;
904 default:
905 if (i >= -128 && i <= 127){
906 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
907 } else
908 ig.Emit (OpCodes.Ldc_I4, i);
909 break;
913 public override void Emit (EmitContext ec)
915 EmitInt (ec.ig, Value);
918 public override string AsString ()
920 return Value.ToString ();
923 public override object GetValue ()
925 return Value;
928 public override Constant Increment ()
930 return new IntConstant (checked(Value + 1), loc);
933 public override bool IsDefaultValue {
934 get {
935 return Value == 0;
939 public override bool IsNegative {
940 get {
941 return Value < 0;
945 public override bool IsZeroInteger {
946 get { return Value == 0; }
949 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
951 if (target_type == TypeManager.byte_type) {
952 if (in_checked_context){
953 if (Value < Byte.MinValue || Value > Byte.MaxValue)
954 throw new OverflowException ();
956 return new ByteConstant ((byte) Value, Location);
958 if (target_type == TypeManager.sbyte_type) {
959 if (in_checked_context){
960 if (Value < SByte.MinValue || Value > SByte.MaxValue)
961 throw new OverflowException ();
963 return new SByteConstant ((sbyte) Value, Location);
965 if (target_type == TypeManager.short_type) {
966 if (in_checked_context){
967 if (Value < Int16.MinValue || Value > Int16.MaxValue)
968 throw new OverflowException ();
970 return new ShortConstant ((short) Value, Location);
972 if (target_type == TypeManager.ushort_type) {
973 if (in_checked_context){
974 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
975 throw new OverflowException ();
977 return new UShortConstant ((ushort) Value, Location);
979 if (target_type == TypeManager.uint32_type) {
980 if (in_checked_context){
981 if (Value < UInt32.MinValue)
982 throw new OverflowException ();
984 return new UIntConstant ((uint) Value, Location);
986 if (target_type == TypeManager.int64_type)
987 return new LongConstant ((long) Value, Location);
988 if (target_type == TypeManager.uint64_type) {
989 if (in_checked_context && Value < 0)
990 throw new OverflowException ();
991 return new ULongConstant ((ulong) Value, Location);
993 if (target_type == TypeManager.float_type)
994 return new FloatConstant ((float) Value, Location);
995 if (target_type == TypeManager.double_type)
996 return new DoubleConstant ((double) Value, Location);
997 if (target_type == TypeManager.char_type) {
998 if (in_checked_context){
999 if (Value < Char.MinValue || Value > Char.MaxValue)
1000 throw new OverflowException ();
1002 return new CharConstant ((char) Value, Location);
1004 if (target_type == TypeManager.decimal_type)
1005 return new DecimalConstant ((decimal) Value, Location);
1007 return null;
1010 public override Constant ConvertImplicitly (Type type)
1012 if (this.type == type)
1013 return this;
1015 Constant c = TryImplicitIntConversion (type);
1016 if (c != null)
1017 return c;
1019 return base.ConvertImplicitly (type);
1022 /// <summary>
1023 /// Attempts to perform an implicit constant conversion of the IntConstant
1024 /// into a different data type using casts (See Implicit Constant
1025 /// Expression Conversions)
1026 /// </summary>
1027 Constant TryImplicitIntConversion (Type target_type)
1029 if (target_type == TypeManager.sbyte_type) {
1030 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1031 return new SByteConstant ((sbyte) Value, loc);
1033 else if (target_type == TypeManager.byte_type) {
1034 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1035 return new ByteConstant ((byte) Value, loc);
1037 else if (target_type == TypeManager.short_type) {
1038 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1039 return new ShortConstant ((short) Value, loc);
1041 else if (target_type == TypeManager.ushort_type) {
1042 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1043 return new UShortConstant ((ushort) Value, loc);
1045 else if (target_type == TypeManager.uint32_type) {
1046 if (Value >= 0)
1047 return new UIntConstant ((uint) Value, loc);
1049 else if (target_type == TypeManager.uint64_type) {
1051 // we can optimize this case: a positive int32
1052 // always fits on a uint64. But we need an opcode
1053 // to do it.
1055 if (Value >= 0)
1056 return new ULongConstant ((ulong) Value, loc);
1058 else if (target_type == TypeManager.double_type)
1059 return new DoubleConstant ((double) Value, loc);
1060 else if (target_type == TypeManager.float_type)
1061 return new FloatConstant ((float) Value, loc);
1063 return null;
1067 public class UIntConstant : IntegralConstant {
1068 public readonly uint Value;
1070 public UIntConstant (uint v, Location loc):
1071 base (loc)
1073 type = TypeManager.uint32_type;
1074 eclass = ExprClass.Value;
1075 Value = v;
1078 public override void Emit (EmitContext ec)
1080 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1083 public override string AsString ()
1085 return Value.ToString ();
1088 public override object GetValue ()
1090 return Value;
1093 public override Constant Increment ()
1095 return new UIntConstant (checked(Value + 1), loc);
1098 public override bool IsDefaultValue {
1099 get {
1100 return Value == 0;
1104 public override bool IsNegative {
1105 get {
1106 return false;
1110 public override bool IsZeroInteger {
1111 get { return Value == 0; }
1114 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1116 if (target_type == TypeManager.byte_type) {
1117 if (in_checked_context){
1118 if (Value < Char.MinValue || Value > Char.MaxValue)
1119 throw new OverflowException ();
1121 return new ByteConstant ((byte) Value, Location);
1123 if (target_type == TypeManager.sbyte_type) {
1124 if (in_checked_context){
1125 if (Value > SByte.MaxValue)
1126 throw new OverflowException ();
1128 return new SByteConstant ((sbyte) Value, Location);
1130 if (target_type == TypeManager.short_type) {
1131 if (in_checked_context){
1132 if (Value > Int16.MaxValue)
1133 throw new OverflowException ();
1135 return new ShortConstant ((short) Value, Location);
1137 if (target_type == TypeManager.ushort_type) {
1138 if (in_checked_context){
1139 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1140 throw new OverflowException ();
1142 return new UShortConstant ((ushort) Value, Location);
1144 if (target_type == TypeManager.int32_type) {
1145 if (in_checked_context){
1146 if (Value > Int32.MaxValue)
1147 throw new OverflowException ();
1149 return new IntConstant ((int) Value, Location);
1151 if (target_type == TypeManager.int64_type)
1152 return new LongConstant ((long) Value, Location);
1153 if (target_type == TypeManager.uint64_type)
1154 return new ULongConstant ((ulong) Value, Location);
1155 if (target_type == TypeManager.float_type)
1156 return new FloatConstant ((float) Value, Location);
1157 if (target_type == TypeManager.double_type)
1158 return new DoubleConstant ((double) Value, Location);
1159 if (target_type == TypeManager.char_type) {
1160 if (in_checked_context){
1161 if (Value < Char.MinValue || Value > Char.MaxValue)
1162 throw new OverflowException ();
1164 return new CharConstant ((char) Value, Location);
1166 if (target_type == TypeManager.decimal_type)
1167 return new DecimalConstant ((decimal) Value, Location);
1169 return null;
1174 public class LongConstant : IntegralConstant {
1175 public readonly long Value;
1177 public LongConstant (long v, Location loc):
1178 base (loc)
1180 type = TypeManager.int64_type;
1181 eclass = ExprClass.Value;
1182 Value = v;
1185 public override void Emit (EmitContext ec)
1187 EmitLong (ec.ig, Value);
1190 static public void EmitLong (ILGenerator ig, long l)
1192 if (l >= int.MinValue && l <= int.MaxValue) {
1193 IntLiteral.EmitInt (ig, unchecked ((int) l));
1194 ig.Emit (OpCodes.Conv_I8);
1195 return;
1198 if (l >= 0 && l <= uint.MaxValue) {
1199 IntLiteral.EmitInt (ig, unchecked ((int) l));
1200 ig.Emit (OpCodes.Conv_U8);
1201 return;
1204 ig.Emit (OpCodes.Ldc_I8, l);
1207 public override string AsString ()
1209 return Value.ToString ();
1212 public override object GetValue ()
1214 return Value;
1217 public override Constant Increment ()
1219 return new LongConstant (checked(Value + 1), loc);
1222 public override bool IsDefaultValue {
1223 get {
1224 return Value == 0;
1228 public override bool IsNegative {
1229 get {
1230 return Value < 0;
1234 public override bool IsZeroInteger {
1235 get { return Value == 0; }
1238 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1240 if (target_type == TypeManager.byte_type) {
1241 if (in_checked_context){
1242 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1243 throw new OverflowException ();
1245 return new ByteConstant ((byte) Value, Location);
1247 if (target_type == TypeManager.sbyte_type) {
1248 if (in_checked_context){
1249 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1250 throw new OverflowException ();
1252 return new SByteConstant ((sbyte) Value, Location);
1254 if (target_type == TypeManager.short_type) {
1255 if (in_checked_context){
1256 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1257 throw new OverflowException ();
1259 return new ShortConstant ((short) Value, Location);
1261 if (target_type == TypeManager.ushort_type) {
1262 if (in_checked_context){
1263 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1264 throw new OverflowException ();
1266 return new UShortConstant ((ushort) Value, Location);
1268 if (target_type == TypeManager.int32_type) {
1269 if (in_checked_context){
1270 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1271 throw new OverflowException ();
1273 return new IntConstant ((int) Value, Location);
1275 if (target_type == TypeManager.uint32_type) {
1276 if (in_checked_context){
1277 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1278 throw new OverflowException ();
1280 return new UIntConstant ((uint) Value, Location);
1282 if (target_type == TypeManager.uint64_type) {
1283 if (in_checked_context && Value < 0)
1284 throw new OverflowException ();
1285 return new ULongConstant ((ulong) Value, Location);
1287 if (target_type == TypeManager.float_type)
1288 return new FloatConstant ((float) Value, Location);
1289 if (target_type == TypeManager.double_type)
1290 return new DoubleConstant ((double) Value, Location);
1291 if (target_type == TypeManager.char_type) {
1292 if (in_checked_context){
1293 if (Value < Char.MinValue || Value > Char.MaxValue)
1294 throw new OverflowException ();
1296 return new CharConstant ((char) Value, Location);
1298 if (target_type == TypeManager.decimal_type)
1299 return new DecimalConstant ((decimal) Value, Location);
1301 return null;
1304 public override Constant ConvertImplicitly (Type type)
1306 if (Value >= 0 && type == TypeManager.uint64_type) {
1307 return new ULongConstant ((ulong) Value, loc);
1310 return base.ConvertImplicitly (type);
1314 public class ULongConstant : IntegralConstant {
1315 public readonly ulong Value;
1317 public ULongConstant (ulong v, Location loc):
1318 base (loc)
1320 type = TypeManager.uint64_type;
1321 eclass = ExprClass.Value;
1322 Value = v;
1325 public override void Emit (EmitContext ec)
1327 ILGenerator ig = ec.ig;
1329 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1332 public override string AsString ()
1334 return Value.ToString ();
1337 public override object GetValue ()
1339 return Value;
1342 public override Constant Increment ()
1344 return new ULongConstant (checked(Value + 1), loc);
1347 public override bool IsDefaultValue {
1348 get {
1349 return Value == 0;
1353 public override bool IsNegative {
1354 get {
1355 return false;
1359 public override bool IsZeroInteger {
1360 get { return Value == 0; }
1363 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1365 if (target_type == TypeManager.byte_type) {
1366 if (in_checked_context && Value > Byte.MaxValue)
1367 throw new OverflowException ();
1368 return new ByteConstant ((byte) Value, Location);
1370 if (target_type == TypeManager.sbyte_type) {
1371 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1372 throw new OverflowException ();
1373 return new SByteConstant ((sbyte) Value, Location);
1375 if (target_type == TypeManager.short_type) {
1376 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1377 throw new OverflowException ();
1378 return new ShortConstant ((short) Value, Location);
1380 if (target_type == TypeManager.ushort_type) {
1381 if (in_checked_context && Value > UInt16.MaxValue)
1382 throw new OverflowException ();
1383 return new UShortConstant ((ushort) Value, Location);
1385 if (target_type == TypeManager.int32_type) {
1386 if (in_checked_context && Value > UInt32.MaxValue)
1387 throw new OverflowException ();
1388 return new IntConstant ((int) Value, Location);
1390 if (target_type == TypeManager.uint32_type) {
1391 if (in_checked_context && Value > UInt32.MaxValue)
1392 throw new OverflowException ();
1393 return new UIntConstant ((uint) Value, Location);
1395 if (target_type == TypeManager.int64_type) {
1396 if (in_checked_context && Value > Int64.MaxValue)
1397 throw new OverflowException ();
1398 return new LongConstant ((long) Value, Location);
1400 if (target_type == TypeManager.float_type)
1401 return new FloatConstant ((float) Value, Location);
1402 if (target_type == TypeManager.double_type)
1403 return new DoubleConstant ((double) Value, Location);
1404 if (target_type == TypeManager.char_type) {
1405 if (in_checked_context && Value > Char.MaxValue)
1406 throw new OverflowException ();
1407 return new CharConstant ((char) Value, Location);
1409 if (target_type == TypeManager.decimal_type)
1410 return new DecimalConstant ((decimal) Value, Location);
1412 return null;
1417 public class FloatConstant : Constant {
1418 public float Value;
1420 public FloatConstant (float v, Location loc):
1421 base (loc)
1423 type = TypeManager.float_type;
1424 eclass = ExprClass.Value;
1425 Value = v;
1428 public override void Emit (EmitContext ec)
1430 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1433 public override string AsString ()
1435 return Value.ToString ();
1438 public override object GetValue ()
1440 return Value;
1443 public override Constant Increment ()
1445 return new FloatConstant (checked(Value + 1), loc);
1448 public override bool IsDefaultValue {
1449 get {
1450 return Value == 0;
1454 public override bool IsNegative {
1455 get {
1456 return Value < 0;
1460 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1462 if (target_type == TypeManager.byte_type) {
1463 if (in_checked_context){
1464 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1465 throw new OverflowException ();
1467 return new ByteConstant ((byte) Value, Location);
1469 if (target_type == TypeManager.sbyte_type) {
1470 if (in_checked_context){
1471 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1472 throw new OverflowException ();
1474 return new SByteConstant ((sbyte) Value, Location);
1476 if (target_type == TypeManager.short_type) {
1477 if (in_checked_context){
1478 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1479 throw new OverflowException ();
1481 return new ShortConstant ((short) Value, Location);
1483 if (target_type == TypeManager.ushort_type) {
1484 if (in_checked_context){
1485 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1486 throw new OverflowException ();
1488 return new UShortConstant ((ushort) Value, Location);
1490 if (target_type == TypeManager.int32_type) {
1491 if (in_checked_context){
1492 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1493 throw new OverflowException ();
1495 return new IntConstant ((int) Value, Location);
1497 if (target_type == TypeManager.uint32_type) {
1498 if (in_checked_context){
1499 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1500 throw new OverflowException ();
1502 return new UIntConstant ((uint) Value, Location);
1504 if (target_type == TypeManager.int64_type) {
1505 if (in_checked_context){
1506 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1507 throw new OverflowException ();
1509 return new LongConstant ((long) Value, Location);
1511 if (target_type == TypeManager.uint64_type) {
1512 if (in_checked_context){
1513 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1514 throw new OverflowException ();
1516 return new ULongConstant ((ulong) Value, Location);
1518 if (target_type == TypeManager.double_type)
1519 return new DoubleConstant ((double) Value, Location);
1520 if (target_type == TypeManager.char_type) {
1521 if (in_checked_context){
1522 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1523 throw new OverflowException ();
1525 return new CharConstant ((char) Value, Location);
1527 if (target_type == TypeManager.decimal_type)
1528 return new DecimalConstant ((decimal) Value, Location);
1530 return null;
1535 public class DoubleConstant : Constant {
1536 public double Value;
1538 public DoubleConstant (double v, Location loc):
1539 base (loc)
1541 type = TypeManager.double_type;
1542 eclass = ExprClass.Value;
1543 Value = v;
1546 public override void Emit (EmitContext ec)
1548 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1551 public override string AsString ()
1553 return Value.ToString ();
1556 public override object GetValue ()
1558 return Value;
1561 public override Constant Increment ()
1563 return new DoubleConstant (checked(Value + 1), loc);
1566 public override bool IsDefaultValue {
1567 get {
1568 return Value == 0;
1572 public override bool IsNegative {
1573 get {
1574 return Value < 0;
1578 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1580 if (target_type == TypeManager.byte_type) {
1581 if (in_checked_context){
1582 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1583 throw new OverflowException ();
1585 return new ByteConstant ((byte) Value, Location);
1587 if (target_type == TypeManager.sbyte_type) {
1588 if (in_checked_context){
1589 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1590 throw new OverflowException ();
1592 return new SByteConstant ((sbyte) Value, Location);
1594 if (target_type == TypeManager.short_type) {
1595 if (in_checked_context){
1596 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1597 throw new OverflowException ();
1599 return new ShortConstant ((short) Value, Location);
1601 if (target_type == TypeManager.ushort_type) {
1602 if (in_checked_context){
1603 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1604 throw new OverflowException ();
1606 return new UShortConstant ((ushort) Value, Location);
1608 if (target_type == TypeManager.int32_type) {
1609 if (in_checked_context){
1610 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1611 throw new OverflowException ();
1613 return new IntConstant ((int) Value, Location);
1615 if (target_type == TypeManager.uint32_type) {
1616 if (in_checked_context){
1617 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1618 throw new OverflowException ();
1620 return new UIntConstant ((uint) Value, Location);
1622 if (target_type == TypeManager.int64_type) {
1623 if (in_checked_context){
1624 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1625 throw new OverflowException ();
1627 return new LongConstant ((long) Value, Location);
1629 if (target_type == TypeManager.uint64_type) {
1630 if (in_checked_context){
1631 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1632 throw new OverflowException ();
1634 return new ULongConstant ((ulong) Value, Location);
1636 if (target_type == TypeManager.float_type)
1637 return new FloatConstant ((float) Value, Location);
1638 if (target_type == TypeManager.char_type) {
1639 if (in_checked_context){
1640 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1641 throw new OverflowException ();
1643 return new CharConstant ((char) Value, Location);
1645 if (target_type == TypeManager.decimal_type)
1646 return new DecimalConstant ((decimal) Value, Location);
1648 return null;
1653 public class DecimalConstant : Constant {
1654 public readonly decimal Value;
1656 public DecimalConstant (decimal d, Location loc):
1657 base (loc)
1659 type = TypeManager.decimal_type;
1660 eclass = ExprClass.Value;
1661 Value = d;
1664 override public string AsString ()
1666 return Value.ToString () + "M";
1669 public override object GetValue ()
1671 return (object) Value;
1674 public override void Emit (EmitContext ec)
1676 ILGenerator ig = ec.ig;
1678 int [] words = decimal.GetBits (Value);
1679 int power = (words [3] >> 16) & 0xff;
1681 if (power == 0) {
1682 if (Value <= int.MaxValue && Value >= int.MinValue) {
1683 if (TypeManager.void_decimal_ctor_int_arg == null) {
1684 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1685 TypeManager.decimal_type, loc, TypeManager.int32_type);
1687 if (TypeManager.void_decimal_ctor_int_arg == null)
1688 return;
1691 IntConstant.EmitInt (ig, (int) Value);
1692 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1693 return;
1696 if (Value <= long.MaxValue && Value >= long.MinValue) {
1697 if (TypeManager.void_decimal_ctor_long_arg == null) {
1698 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1699 TypeManager.decimal_type, loc, TypeManager.int64_type);
1701 if (TypeManager.void_decimal_ctor_long_arg == null)
1702 return;
1705 LongConstant.EmitLong (ig, (long) Value);
1706 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1707 return;
1711 IntConstant.EmitInt (ig, words [0]);
1712 IntConstant.EmitInt (ig, words [1]);
1713 IntConstant.EmitInt (ig, words [2]);
1715 // sign
1716 IntConstant.EmitInt (ig, words [3] >> 31);
1718 // power
1719 IntConstant.EmitInt (ig, power);
1721 if (TypeManager.void_decimal_ctor_five_args == null) {
1722 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1723 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1724 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1726 if (TypeManager.void_decimal_ctor_five_args == null)
1727 return;
1730 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1733 public override Constant Increment ()
1735 return new DecimalConstant (checked (Value + 1), loc);
1738 public override bool IsDefaultValue {
1739 get {
1740 return Value == 0;
1744 public override bool IsNegative {
1745 get {
1746 return Value < 0;
1750 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1752 if (target_type == TypeManager.sbyte_type)
1753 return new SByteConstant ((sbyte)Value, loc);
1754 if (target_type == TypeManager.byte_type)
1755 return new ByteConstant ((byte)Value, loc);
1756 if (target_type == TypeManager.short_type)
1757 return new ShortConstant ((short)Value, loc);
1758 if (target_type == TypeManager.ushort_type)
1759 return new UShortConstant ((ushort)Value, loc);
1760 if (target_type == TypeManager.int32_type)
1761 return new IntConstant ((int)Value, loc);
1762 if (target_type == TypeManager.uint32_type)
1763 return new UIntConstant ((uint)Value, loc);
1764 if (target_type == TypeManager.int64_type)
1765 return new LongConstant ((long)Value, loc);
1766 if (target_type == TypeManager.uint64_type)
1767 return new ULongConstant ((ulong)Value, loc);
1768 if (target_type == TypeManager.char_type)
1769 return new CharConstant ((char)Value, loc);
1770 if (target_type == TypeManager.float_type)
1771 return new FloatConstant ((float)Value, loc);
1772 if (target_type == TypeManager.double_type)
1773 return new DoubleConstant ((double)Value, loc);
1775 return null;
1780 public class StringConstant : Constant {
1781 public readonly string Value;
1783 public StringConstant (string s, Location loc):
1784 base (loc)
1786 type = TypeManager.string_type;
1787 eclass = ExprClass.Value;
1788 Value = s;
1791 // FIXME: Escape the string.
1792 override public string AsString ()
1794 return "\"" + Value + "\"";
1797 public override object GetValue ()
1799 return Value;
1802 public override void Emit (EmitContext ec)
1804 if (Value == null) {
1805 ec.ig.Emit (OpCodes.Ldnull);
1806 return;
1810 // Use string.Empty for both literals and constants even if
1811 // it's not allowed at language level
1813 if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) {
1814 if (TypeManager.string_empty == null)
1815 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
1817 if (TypeManager.string_empty != null) {
1818 ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1819 return;
1823 ec.ig.Emit (OpCodes.Ldstr, Value);
1826 public override Constant Increment ()
1828 throw new NotSupportedException ();
1831 public override bool IsDefaultValue {
1832 get {
1833 return Value == null;
1837 public override bool IsNegative {
1838 get {
1839 return false;
1843 public override bool IsNull {
1844 get {
1845 return IsDefaultValue;
1849 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1851 return null;
1856 // Null constant can have its own type, think of `default (Foo)'
1858 public class NullConstant : Constant
1860 public NullConstant (Type type, Location loc)
1861 : base (loc)
1863 eclass = ExprClass.Value;
1864 this.type = type;
1867 public override string AsString ()
1869 return GetSignatureForError ();
1872 public override Expression DoResolve (ResolveContext ec)
1874 return this;
1877 public override void Emit (EmitContext ec)
1879 ec.ig.Emit (OpCodes.Ldnull);
1881 // Only to make verifier happy
1882 if (TypeManager.IsGenericParameter (type))
1883 ec.ig.Emit (OpCodes.Unbox_Any, type);
1886 public override string ExprClassName {
1887 get {
1888 return GetSignatureForError ();
1892 public override string GetSignatureForError ()
1894 return "null";
1897 public override Constant ConvertExplicitly (bool inCheckedContext, Type targetType)
1899 if (targetType.IsPointer) {
1900 if (IsLiteral || this is NullPointer)
1901 return new EmptyConstantCast (new NullPointer (loc), targetType);
1903 return null;
1906 // Exlude internal compiler types
1907 if (targetType == InternalType.AnonymousMethod)
1908 return null;
1910 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
1911 return null;
1913 if (TypeManager.IsReferenceType (targetType))
1914 return new NullConstant (targetType, loc);
1916 if (TypeManager.IsNullableType (targetType))
1917 return Nullable.LiftedNull.Create (targetType, loc);
1919 return null;
1922 public override Constant ConvertImplicitly (Type targetType)
1924 return ConvertExplicitly (false, targetType);
1927 public override object GetValue ()
1929 return null;
1932 public override Constant Increment ()
1934 throw new NotSupportedException ();
1937 public override bool IsDefaultValue {
1938 get { return true; }
1941 public override bool IsNegative {
1942 get { return false; }
1945 public override bool IsNull {
1946 get { return true; }
1949 public override bool IsZeroInteger {
1950 get { return true; }
1953 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1955 type = storey.MutateType (type);
1959 /// <summary>
1960 /// The value is constant, but when emitted has a side effect. This is
1961 /// used by BitwiseAnd to ensure that the second expression is invoked
1962 /// regardless of the value of the left side.
1963 /// </summary>
1964 public class SideEffectConstant : Constant {
1965 public Constant value;
1966 Expression side_effect;
1968 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
1970 this.value = value;
1971 while (side_effect is SideEffectConstant)
1972 side_effect = ((SideEffectConstant) side_effect).side_effect;
1973 this.side_effect = side_effect;
1974 eclass = ExprClass.Value;
1975 type = value.Type;
1978 public override string AsString ()
1980 return value.AsString ();
1983 public override object GetValue ()
1985 return value.GetValue ();
1988 public override void Emit (EmitContext ec)
1990 side_effect.EmitSideEffect (ec);
1991 value.Emit (ec);
1994 public override void EmitSideEffect (EmitContext ec)
1996 side_effect.EmitSideEffect (ec);
1997 value.EmitSideEffect (ec);
2000 public override bool IsDefaultValue {
2001 get { return value.IsDefaultValue; }
2004 public override Constant Increment ()
2006 throw new NotSupportedException ();
2009 public override bool IsNegative {
2010 get { return value.IsNegative; }
2013 public override bool IsZeroInteger {
2014 get { return value.IsZeroInteger; }
2017 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
2019 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2020 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);