2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
15 using IKVM.Reflection.Emit;
17 using System.Reflection.Emit;
20 namespace Mono.CSharp {
23 /// Base class for constants and literals.
25 public abstract class Constant : Expression {
27 protected Constant (Location loc)
33 /// This is different from ToString in that ToString
34 /// is supposed to be there for debugging purposes,
35 /// and is not guaranteed to be useful for anything else,
36 /// AsString() will provide something that can be used
37 /// for round-tripping C# code. Maybe it can be used
38 /// for IL assembly as well.
40 public abstract string AsString ();
42 override public string ToString ()
44 return this.GetType ().Name + " (" + AsString () + ")";
48 /// This is used to obtain the actual value of the literal
49 /// cast into an object.
51 public abstract object GetValue ();
55 // Returns an object value which is typed to contant type
57 public virtual object GetTypedValue ()
63 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
65 if (!expl && IsLiteral &&
66 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
67 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
68 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
69 AsString (), TypeManager.CSharpName (target));
71 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
75 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
77 Constant c = ConvertImplicitly (ec, type);
79 Error_ValueCannotBeConverted (ec, loc, type, false);
84 public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
86 if (this.type == type)
89 if (Convert.ImplicitNumericConversion (this, type) == null)
93 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
96 // We should always catch the error before this is ever
97 // reached, by calling Convert.ImplicitStandardConversionExists
99 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
100 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
103 return CreateConstant (rc, type, constant_value, loc);
107 // Returns a constant instance based on Type
109 public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc)
111 return CreateConstantFromValue (t, v, loc).Resolve (rc);
114 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
116 if (t == TypeManager.int32_type)
117 return new IntConstant ((int) v, loc);
118 if (t == TypeManager.string_type)
119 return new StringConstant ((string) v, loc);
120 if (t == TypeManager.uint32_type)
121 return new UIntConstant ((uint) v, loc);
122 if (t == TypeManager.int64_type)
123 return new LongConstant ((long) v, loc);
124 if (t == TypeManager.uint64_type)
125 return new ULongConstant ((ulong) v, loc);
126 if (t == TypeManager.float_type)
127 return new FloatConstant ((float) v, loc);
128 if (t == TypeManager.double_type)
129 return new DoubleConstant ((double) v, loc);
130 if (t == TypeManager.short_type)
131 return new ShortConstant ((short)v, loc);
132 if (t == TypeManager.ushort_type)
133 return new UShortConstant ((ushort)v, loc);
134 if (t == TypeManager.sbyte_type)
135 return new SByteConstant ((sbyte)v, loc);
136 if (t == TypeManager.byte_type)
137 return new ByteConstant ((byte)v, loc);
138 if (t == TypeManager.char_type)
139 return new CharConstant ((char)v, loc);
140 if (t == TypeManager.bool_type)
141 return new BoolConstant ((bool) v, loc);
142 if (t == TypeManager.decimal_type)
143 return new DecimalConstant ((decimal) v, loc);
144 if (TypeManager.IsEnumType (t)) {
145 var real_type = EnumSpec.GetUnderlyingType (t);
146 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
149 if (TypeManager.IsNullableType (t))
150 return Nullable.LiftedNull.Create (t, loc);
152 if (TypeManager.IsReferenceType (t))
153 return new NullConstant (t, loc);
156 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
157 v, TypeManager.CSharpName (t));
160 public override Expression CreateExpressionTree (ResolveContext ec)
162 Arguments args = new Arguments (2);
163 args.Add (new Argument (this));
164 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
166 return CreateExpressionFactoryCall (ec, "Constant", args);
171 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
172 /// It throws OverflowException
174 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
175 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
178 /// Attempts to do a compile-time folding of a constant cast.
180 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
183 return TryReduce (ec, target_type);
185 catch (OverflowException) {
186 if (ec.ConstantCheckState) {
187 ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
188 GetValue ().ToString (), TypeManager.CSharpName (target_type));
190 Error_ValueCannotBeConverted (ec, loc, target_type, false);
193 return New.Constantify (target_type, loc).Resolve (ec);
197 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
199 if (Type == target_type)
203 if (TypeManager.IsEnumType (target_type)) {
204 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
208 return new EnumConstant (c, target_type).Resolve (ec);
211 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
219 /// Need to pass type as the constant can require a boxing
220 /// and in such case no optimization is possible
222 public bool IsDefaultInitializer (TypeSpec type)
225 return IsDefaultValue;
227 return this is NullLiteral;
230 public abstract bool IsDefaultValue {
234 public abstract bool IsNegative {
239 // When constant is declared as literal
241 public virtual bool IsLiteral {
242 get { return false; }
245 public virtual bool IsOneInteger {
246 get { return false; }
250 // Returns true iff 1) the stack type of this is one of Object,
251 // int32, int64 and 2) this == 0 or this == null.
253 public virtual bool IsZeroInteger {
254 get { return false; }
257 public override void EmitSideEffect (EmitContext ec)
262 public sealed override Expression Clone (CloneContext clonectx)
264 // No cloning is not needed for constants
268 protected override void CloneTo (CloneContext clonectx, Expression target)
270 throw new NotSupportedException ("should not be reached");
273 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
276 return base.MakeExpression (ctx);
278 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
282 public new Constant Resolve (ResolveContext rc)
284 if (eclass != ExprClass.Unresolved)
287 // Resolved constant has to be still a constant
288 Constant c = (Constant) DoResolve (rc);
292 if ((c.eclass & ExprClass.Value) == 0) {
293 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
298 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
304 public abstract class IntegralConstant : Constant
306 protected IntegralConstant (Location loc) :
311 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
314 ConvertExplicitly (true, target);
315 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
319 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
320 GetValue ().ToString (), TypeManager.CSharpName (target));
324 public abstract Constant Increment ();
327 public class BoolConstant : Constant {
328 public readonly bool Value;
330 public BoolConstant (bool val, Location loc):
336 override public string AsString ()
338 return Value ? "true" : "false";
341 protected override Expression DoResolve (ResolveContext ec)
343 type = TypeManager.bool_type;
344 eclass = ExprClass.Value;
348 public override object GetValue ()
350 return (object) Value;
353 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
355 enc.Stream.Write (Value);
358 public override void Emit (EmitContext ec)
361 ec.Emit (OpCodes.Ldc_I4_1);
363 ec.Emit (OpCodes.Ldc_I4_0);
366 public override bool IsDefaultValue {
372 public override bool IsNegative {
378 public override bool IsZeroInteger {
379 get { return Value == false; }
382 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
389 public class ByteConstant : IntegralConstant {
390 public readonly byte Value;
392 public ByteConstant (byte v, Location loc):
398 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
400 enc.Stream.Write (Value);
403 public override void Emit (EmitContext ec)
408 public override string AsString ()
410 return Value.ToString ();
413 protected override Expression DoResolve (ResolveContext ec)
415 type = TypeManager.byte_type;
416 eclass = ExprClass.Value;
420 public override object GetValue ()
425 public override Constant Increment ()
427 return new ByteConstant (checked ((byte)(Value + 1)), loc);
430 public override bool IsDefaultValue {
436 public override bool IsOneInteger {
442 public override bool IsNegative {
448 public override bool IsZeroInteger {
449 get { return Value == 0; }
452 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
454 if (target_type == TypeManager.sbyte_type) {
455 if (in_checked_context){
456 if (Value > SByte.MaxValue)
457 throw new OverflowException ();
459 return new SByteConstant ((sbyte) Value, Location);
461 if (target_type == TypeManager.short_type)
462 return new ShortConstant ((short) Value, Location);
463 if (target_type == TypeManager.ushort_type)
464 return new UShortConstant ((ushort) Value, Location);
465 if (target_type == TypeManager.int32_type)
466 return new IntConstant ((int) Value, Location);
467 if (target_type == TypeManager.uint32_type)
468 return new UIntConstant ((uint) Value, Location);
469 if (target_type == TypeManager.int64_type)
470 return new LongConstant ((long) Value, Location);
471 if (target_type == TypeManager.uint64_type)
472 return new ULongConstant ((ulong) Value, Location);
473 if (target_type == TypeManager.float_type)
474 return new FloatConstant ((float) Value, Location);
475 if (target_type == TypeManager.double_type)
476 return new DoubleConstant ((double) Value, Location);
477 if (target_type == TypeManager.char_type)
478 return new CharConstant ((char) Value, Location);
479 if (target_type == TypeManager.decimal_type)
480 return new DecimalConstant ((decimal) Value, Location);
487 public class CharConstant : Constant {
488 public readonly char Value;
490 public CharConstant (char v, Location loc):
496 protected override Expression DoResolve (ResolveContext rc)
498 type = TypeManager.char_type;
499 eclass = ExprClass.Value;
503 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
505 enc.Stream.Write ((ushort) Value);
508 public override void Emit (EmitContext ec)
513 static string descape (char c)
539 return c.ToString ();
542 public override string AsString ()
544 return "\"" + descape (Value) + "\"";
547 public override object GetValue ()
552 public override bool IsDefaultValue {
558 public override bool IsNegative {
564 public override bool IsZeroInteger {
565 get { return Value == '\0'; }
568 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
570 if (target_type == TypeManager.byte_type) {
571 if (in_checked_context){
572 if (Value < Byte.MinValue || Value > Byte.MaxValue)
573 throw new OverflowException ();
575 return new ByteConstant ((byte) Value, Location);
577 if (target_type == TypeManager.sbyte_type) {
578 if (in_checked_context){
579 if (Value > SByte.MaxValue)
580 throw new OverflowException ();
582 return new SByteConstant ((sbyte) Value, Location);
584 if (target_type == TypeManager.short_type) {
585 if (in_checked_context){
586 if (Value > Int16.MaxValue)
587 throw new OverflowException ();
589 return new ShortConstant ((short) Value, Location);
591 if (target_type == TypeManager.int32_type)
592 return new IntConstant ((int) Value, Location);
593 if (target_type == TypeManager.uint32_type)
594 return new UIntConstant ((uint) Value, Location);
595 if (target_type == TypeManager.int64_type)
596 return new LongConstant ((long) Value, Location);
597 if (target_type == TypeManager.uint64_type)
598 return new ULongConstant ((ulong) Value, Location);
599 if (target_type == TypeManager.float_type)
600 return new FloatConstant ((float) Value, Location);
601 if (target_type == TypeManager.double_type)
602 return new DoubleConstant ((double) Value, Location);
603 if (target_type == TypeManager.decimal_type)
604 return new DecimalConstant ((decimal) Value, Location);
611 public class SByteConstant : IntegralConstant {
612 public readonly sbyte Value;
614 public SByteConstant (sbyte v, Location loc):
620 protected override Expression DoResolve (ResolveContext rc)
622 type = TypeManager.sbyte_type;
623 eclass = ExprClass.Value;
627 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
629 enc.Stream.Write (Value);
632 public override void Emit (EmitContext ec)
637 public override string AsString ()
639 return Value.ToString ();
642 public override object GetValue ()
647 public override Constant Increment ()
649 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
652 public override bool IsDefaultValue {
658 public override bool IsNegative {
664 public override bool IsOneInteger {
670 public override bool IsZeroInteger {
671 get { return Value == 0; }
674 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
676 if (target_type == TypeManager.byte_type) {
677 if (in_checked_context && Value < 0)
678 throw new OverflowException ();
679 return new ByteConstant ((byte) Value, Location);
681 if (target_type == TypeManager.short_type)
682 return new ShortConstant ((short) Value, Location);
683 if (target_type == TypeManager.ushort_type) {
684 if (in_checked_context && Value < 0)
685 throw new OverflowException ();
686 return new UShortConstant ((ushort) Value, Location);
687 } if (target_type == TypeManager.int32_type)
688 return new IntConstant ((int) Value, Location);
689 if (target_type == TypeManager.uint32_type) {
690 if (in_checked_context && Value < 0)
691 throw new OverflowException ();
692 return new UIntConstant ((uint) Value, Location);
693 } if (target_type == TypeManager.int64_type)
694 return new LongConstant ((long) Value, Location);
695 if (target_type == TypeManager.uint64_type) {
696 if (in_checked_context && Value < 0)
697 throw new OverflowException ();
698 return new ULongConstant ((ulong) Value, Location);
700 if (target_type == TypeManager.float_type)
701 return new FloatConstant ((float) Value, Location);
702 if (target_type == TypeManager.double_type)
703 return new DoubleConstant ((double) Value, Location);
704 if (target_type == TypeManager.char_type) {
705 if (in_checked_context && Value < 0)
706 throw new OverflowException ();
707 return new CharConstant ((char) Value, Location);
709 if (target_type == TypeManager.decimal_type)
710 return new DecimalConstant ((decimal) Value, Location);
717 public class ShortConstant : IntegralConstant {
718 public readonly short Value;
720 public ShortConstant (short v, Location loc):
726 protected override Expression DoResolve (ResolveContext rc)
728 type = TypeManager.short_type;
729 eclass = ExprClass.Value;
733 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
735 enc.Stream.Write (Value);
738 public override void Emit (EmitContext ec)
743 public override string AsString ()
745 return Value.ToString ();
748 public override object GetValue ()
753 public override Constant Increment ()
755 return new ShortConstant (checked((short)(Value + 1)), loc);
758 public override bool IsDefaultValue {
764 public override bool IsZeroInteger {
765 get { return Value == 0; }
768 public override bool IsNegative {
774 public override bool IsOneInteger {
780 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
782 if (target_type == TypeManager.byte_type) {
783 if (in_checked_context){
784 if (Value < Byte.MinValue || Value > Byte.MaxValue)
785 throw new OverflowException ();
787 return new ByteConstant ((byte) Value, Location);
789 if (target_type == TypeManager.sbyte_type) {
790 if (in_checked_context){
791 if (Value < SByte.MinValue || Value > SByte.MaxValue)
792 throw new OverflowException ();
794 return new SByteConstant ((sbyte) Value, Location);
796 if (target_type == TypeManager.ushort_type) {
797 if (in_checked_context && Value < 0)
798 throw new OverflowException ();
800 return new UShortConstant ((ushort) Value, Location);
802 if (target_type == TypeManager.int32_type)
803 return new IntConstant ((int) Value, Location);
804 if (target_type == TypeManager.uint32_type) {
805 if (in_checked_context && Value < 0)
806 throw new OverflowException ();
807 return new UIntConstant ((uint) Value, Location);
809 if (target_type == TypeManager.int64_type)
810 return new LongConstant ((long) Value, Location);
811 if (target_type == TypeManager.uint64_type) {
812 if (in_checked_context && Value < 0)
813 throw new OverflowException ();
814 return new ULongConstant ((ulong) Value, Location);
816 if (target_type == TypeManager.float_type)
817 return new FloatConstant ((float) Value, Location);
818 if (target_type == TypeManager.double_type)
819 return new DoubleConstant ((double) Value, Location);
820 if (target_type == TypeManager.char_type) {
821 if (in_checked_context){
822 if (Value < Char.MinValue)
823 throw new OverflowException ();
825 return new CharConstant ((char) Value, Location);
827 if (target_type == TypeManager.decimal_type)
828 return new DecimalConstant ((decimal) Value, Location);
835 public class UShortConstant : IntegralConstant {
836 public readonly ushort Value;
838 public UShortConstant (ushort v, Location loc):
844 protected override Expression DoResolve (ResolveContext rc)
846 type = TypeManager.ushort_type;
847 eclass = ExprClass.Value;
851 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
853 enc.Stream.Write (Value);
856 public override void Emit (EmitContext ec)
861 public override string AsString ()
863 return Value.ToString ();
866 public override object GetValue ()
871 public override Constant Increment ()
873 return new UShortConstant (checked((ushort)(Value + 1)), loc);
876 public override bool IsDefaultValue {
882 public override bool IsNegative {
888 public override bool IsOneInteger {
894 public override bool IsZeroInteger {
895 get { return Value == 0; }
898 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
900 if (target_type == TypeManager.byte_type) {
901 if (in_checked_context){
902 if (Value > Byte.MaxValue)
903 throw new OverflowException ();
905 return new ByteConstant ((byte) Value, Location);
907 if (target_type == TypeManager.sbyte_type) {
908 if (in_checked_context){
909 if (Value > SByte.MaxValue)
910 throw new OverflowException ();
912 return new SByteConstant ((sbyte) Value, Location);
914 if (target_type == TypeManager.short_type) {
915 if (in_checked_context){
916 if (Value > Int16.MaxValue)
917 throw new OverflowException ();
919 return new ShortConstant ((short) Value, Location);
921 if (target_type == TypeManager.int32_type)
922 return new IntConstant ((int) Value, Location);
923 if (target_type == TypeManager.uint32_type)
924 return new UIntConstant ((uint) Value, Location);
925 if (target_type == TypeManager.int64_type)
926 return new LongConstant ((long) Value, Location);
927 if (target_type == TypeManager.uint64_type)
928 return new ULongConstant ((ulong) Value, Location);
929 if (target_type == TypeManager.float_type)
930 return new FloatConstant ((float) Value, Location);
931 if (target_type == TypeManager.double_type)
932 return new DoubleConstant ((double) Value, Location);
933 if (target_type == TypeManager.char_type) {
934 if (in_checked_context){
935 if (Value > Char.MaxValue)
936 throw new OverflowException ();
938 return new CharConstant ((char) Value, Location);
940 if (target_type == TypeManager.decimal_type)
941 return new DecimalConstant ((decimal) Value, Location);
947 public class IntConstant : IntegralConstant {
948 public readonly int Value;
950 public IntConstant (int v, Location loc):
956 protected override Expression DoResolve (ResolveContext rc)
958 type = TypeManager.int32_type;
959 eclass = ExprClass.Value;
963 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
965 enc.Stream.Write (Value);
968 public override void Emit (EmitContext ec)
973 public override string AsString ()
975 return Value.ToString ();
978 public override object GetValue ()
983 public override Constant Increment ()
985 return new IntConstant (checked(Value + 1), loc);
988 public override bool IsDefaultValue {
994 public override bool IsNegative {
1000 public override bool IsOneInteger {
1006 public override bool IsZeroInteger {
1007 get { return Value == 0; }
1010 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1012 if (target_type == TypeManager.byte_type) {
1013 if (in_checked_context){
1014 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1015 throw new OverflowException ();
1017 return new ByteConstant ((byte) Value, Location);
1019 if (target_type == TypeManager.sbyte_type) {
1020 if (in_checked_context){
1021 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1022 throw new OverflowException ();
1024 return new SByteConstant ((sbyte) Value, Location);
1026 if (target_type == TypeManager.short_type) {
1027 if (in_checked_context){
1028 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1029 throw new OverflowException ();
1031 return new ShortConstant ((short) Value, Location);
1033 if (target_type == TypeManager.ushort_type) {
1034 if (in_checked_context){
1035 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1036 throw new OverflowException ();
1038 return new UShortConstant ((ushort) Value, Location);
1040 if (target_type == TypeManager.uint32_type) {
1041 if (in_checked_context){
1042 if (Value < UInt32.MinValue)
1043 throw new OverflowException ();
1045 return new UIntConstant ((uint) Value, Location);
1047 if (target_type == TypeManager.int64_type)
1048 return new LongConstant ((long) Value, Location);
1049 if (target_type == TypeManager.uint64_type) {
1050 if (in_checked_context && Value < 0)
1051 throw new OverflowException ();
1052 return new ULongConstant ((ulong) Value, Location);
1054 if (target_type == TypeManager.float_type)
1055 return new FloatConstant ((float) Value, Location);
1056 if (target_type == TypeManager.double_type)
1057 return new DoubleConstant ((double) Value, Location);
1058 if (target_type == TypeManager.char_type) {
1059 if (in_checked_context){
1060 if (Value < Char.MinValue || Value > Char.MaxValue)
1061 throw new OverflowException ();
1063 return new CharConstant ((char) Value, Location);
1065 if (target_type == TypeManager.decimal_type)
1066 return new DecimalConstant ((decimal) Value, Location);
1071 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1073 if (this.type == type)
1076 Constant c = TryImplicitIntConversion (type);
1078 return c.Resolve (rc);
1080 return base.ConvertImplicitly (rc, type);
1084 /// Attempts to perform an implicit constant conversion of the IntConstant
1085 /// into a different data type using casts (See Implicit Constant
1086 /// Expression Conversions)
1088 Constant TryImplicitIntConversion (TypeSpec target_type)
1090 if (target_type == TypeManager.sbyte_type) {
1091 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1092 return new SByteConstant ((sbyte) Value, loc);
1094 else if (target_type == TypeManager.byte_type) {
1095 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1096 return new ByteConstant ((byte) Value, loc);
1098 else if (target_type == TypeManager.short_type) {
1099 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1100 return new ShortConstant ((short) Value, loc);
1102 else if (target_type == TypeManager.ushort_type) {
1103 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1104 return new UShortConstant ((ushort) Value, loc);
1106 else if (target_type == TypeManager.uint32_type) {
1108 return new UIntConstant ((uint) Value, loc);
1110 else if (target_type == TypeManager.uint64_type) {
1112 // we can optimize this case: a positive int32
1113 // always fits on a uint64. But we need an opcode
1117 return new ULongConstant ((ulong) Value, loc);
1119 else if (target_type == TypeManager.double_type)
1120 return new DoubleConstant ((double) Value, loc);
1121 else if (target_type == TypeManager.float_type)
1122 return new FloatConstant ((float) Value, loc);
1128 public class UIntConstant : IntegralConstant {
1129 public readonly uint Value;
1131 public UIntConstant (uint v, Location loc):
1137 protected override Expression DoResolve (ResolveContext rc)
1139 type = TypeManager.uint32_type;
1140 eclass = ExprClass.Value;
1144 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1146 enc.Stream.Write (Value);
1149 public override void Emit (EmitContext ec)
1151 ec.EmitInt (unchecked ((int) Value));
1154 public override string AsString ()
1156 return Value.ToString ();
1159 public override object GetValue ()
1164 public override Constant Increment ()
1166 return new UIntConstant (checked(Value + 1), loc);
1169 public override bool IsDefaultValue {
1175 public override bool IsNegative {
1181 public override bool IsOneInteger {
1187 public override bool IsZeroInteger {
1188 get { return Value == 0; }
1191 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1193 if (target_type == TypeManager.byte_type) {
1194 if (in_checked_context){
1195 if (Value < Char.MinValue || Value > Char.MaxValue)
1196 throw new OverflowException ();
1198 return new ByteConstant ((byte) Value, Location);
1200 if (target_type == TypeManager.sbyte_type) {
1201 if (in_checked_context){
1202 if (Value > SByte.MaxValue)
1203 throw new OverflowException ();
1205 return new SByteConstant ((sbyte) Value, Location);
1207 if (target_type == TypeManager.short_type) {
1208 if (in_checked_context){
1209 if (Value > Int16.MaxValue)
1210 throw new OverflowException ();
1212 return new ShortConstant ((short) Value, Location);
1214 if (target_type == TypeManager.ushort_type) {
1215 if (in_checked_context){
1216 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1217 throw new OverflowException ();
1219 return new UShortConstant ((ushort) Value, Location);
1221 if (target_type == TypeManager.int32_type) {
1222 if (in_checked_context){
1223 if (Value > Int32.MaxValue)
1224 throw new OverflowException ();
1226 return new IntConstant ((int) Value, Location);
1228 if (target_type == TypeManager.int64_type)
1229 return new LongConstant ((long) Value, Location);
1230 if (target_type == TypeManager.uint64_type)
1231 return new ULongConstant ((ulong) Value, Location);
1232 if (target_type == TypeManager.float_type)
1233 return new FloatConstant ((float) Value, Location);
1234 if (target_type == TypeManager.double_type)
1235 return new DoubleConstant ((double) Value, Location);
1236 if (target_type == TypeManager.char_type) {
1237 if (in_checked_context){
1238 if (Value < Char.MinValue || Value > Char.MaxValue)
1239 throw new OverflowException ();
1241 return new CharConstant ((char) Value, Location);
1243 if (target_type == TypeManager.decimal_type)
1244 return new DecimalConstant ((decimal) Value, Location);
1251 public class LongConstant : IntegralConstant {
1252 public readonly long Value;
1254 public LongConstant (long v, Location loc):
1260 protected override Expression DoResolve (ResolveContext rc)
1262 type = TypeManager.int64_type;
1263 eclass = ExprClass.Value;
1267 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1269 enc.Stream.Write (Value);
1272 public override void Emit (EmitContext ec)
1274 ec.EmitLong (Value);
1277 public override string AsString ()
1279 return Value.ToString ();
1282 public override object GetValue ()
1287 public override Constant Increment ()
1289 return new LongConstant (checked(Value + 1), loc);
1292 public override bool IsDefaultValue {
1298 public override bool IsNegative {
1304 public override bool IsOneInteger {
1310 public override bool IsZeroInteger {
1311 get { return Value == 0; }
1314 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1316 if (target_type == TypeManager.byte_type) {
1317 if (in_checked_context){
1318 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1319 throw new OverflowException ();
1321 return new ByteConstant ((byte) Value, Location);
1323 if (target_type == TypeManager.sbyte_type) {
1324 if (in_checked_context){
1325 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1326 throw new OverflowException ();
1328 return new SByteConstant ((sbyte) Value, Location);
1330 if (target_type == TypeManager.short_type) {
1331 if (in_checked_context){
1332 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1333 throw new OverflowException ();
1335 return new ShortConstant ((short) Value, Location);
1337 if (target_type == TypeManager.ushort_type) {
1338 if (in_checked_context){
1339 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1340 throw new OverflowException ();
1342 return new UShortConstant ((ushort) Value, Location);
1344 if (target_type == TypeManager.int32_type) {
1345 if (in_checked_context){
1346 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1347 throw new OverflowException ();
1349 return new IntConstant ((int) Value, Location);
1351 if (target_type == TypeManager.uint32_type) {
1352 if (in_checked_context){
1353 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1354 throw new OverflowException ();
1356 return new UIntConstant ((uint) Value, Location);
1358 if (target_type == TypeManager.uint64_type) {
1359 if (in_checked_context && Value < 0)
1360 throw new OverflowException ();
1361 return new ULongConstant ((ulong) Value, Location);
1363 if (target_type == TypeManager.float_type)
1364 return new FloatConstant ((float) Value, Location);
1365 if (target_type == TypeManager.double_type)
1366 return new DoubleConstant ((double) Value, Location);
1367 if (target_type == TypeManager.char_type) {
1368 if (in_checked_context){
1369 if (Value < Char.MinValue || Value > Char.MaxValue)
1370 throw new OverflowException ();
1372 return new CharConstant ((char) Value, Location);
1374 if (target_type == TypeManager.decimal_type)
1375 return new DecimalConstant ((decimal) Value, Location);
1380 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1382 if (Value >= 0 && type == TypeManager.uint64_type) {
1383 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1386 return base.ConvertImplicitly (rc, type);
1390 public class ULongConstant : IntegralConstant {
1391 public readonly ulong Value;
1393 public ULongConstant (ulong v, Location loc):
1399 protected override Expression DoResolve (ResolveContext rc)
1401 type = TypeManager.uint64_type;
1402 eclass = ExprClass.Value;
1406 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1408 enc.Stream.Write (Value);
1411 public override void Emit (EmitContext ec)
1413 ec.EmitLong (unchecked ((long) Value));
1416 public override string AsString ()
1418 return Value.ToString ();
1421 public override object GetValue ()
1426 public override Constant Increment ()
1428 return new ULongConstant (checked(Value + 1), loc);
1431 public override bool IsDefaultValue {
1437 public override bool IsNegative {
1443 public override bool IsOneInteger {
1449 public override bool IsZeroInteger {
1450 get { return Value == 0; }
1453 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1455 if (target_type == TypeManager.byte_type) {
1456 if (in_checked_context && Value > Byte.MaxValue)
1457 throw new OverflowException ();
1458 return new ByteConstant ((byte) Value, Location);
1460 if (target_type == TypeManager.sbyte_type) {
1461 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1462 throw new OverflowException ();
1463 return new SByteConstant ((sbyte) Value, Location);
1465 if (target_type == TypeManager.short_type) {
1466 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1467 throw new OverflowException ();
1468 return new ShortConstant ((short) Value, Location);
1470 if (target_type == TypeManager.ushort_type) {
1471 if (in_checked_context && Value > UInt16.MaxValue)
1472 throw new OverflowException ();
1473 return new UShortConstant ((ushort) Value, Location);
1475 if (target_type == TypeManager.int32_type) {
1476 if (in_checked_context && Value > UInt32.MaxValue)
1477 throw new OverflowException ();
1478 return new IntConstant ((int) Value, Location);
1480 if (target_type == TypeManager.uint32_type) {
1481 if (in_checked_context && Value > UInt32.MaxValue)
1482 throw new OverflowException ();
1483 return new UIntConstant ((uint) Value, Location);
1485 if (target_type == TypeManager.int64_type) {
1486 if (in_checked_context && Value > Int64.MaxValue)
1487 throw new OverflowException ();
1488 return new LongConstant ((long) Value, Location);
1490 if (target_type == TypeManager.float_type)
1491 return new FloatConstant ((float) Value, Location);
1492 if (target_type == TypeManager.double_type)
1493 return new DoubleConstant ((double) Value, Location);
1494 if (target_type == TypeManager.char_type) {
1495 if (in_checked_context && Value > Char.MaxValue)
1496 throw new OverflowException ();
1497 return new CharConstant ((char) Value, Location);
1499 if (target_type == TypeManager.decimal_type)
1500 return new DecimalConstant ((decimal) Value, Location);
1507 public class FloatConstant : Constant {
1510 public FloatConstant (float v, Location loc):
1516 protected override Expression DoResolve (ResolveContext rc)
1518 type = TypeManager.float_type;
1519 eclass = ExprClass.Value;
1523 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1525 enc.Stream.Write (Value);
1528 public override void Emit (EmitContext ec)
1530 ec.Emit (OpCodes.Ldc_R4, Value);
1533 public override string AsString ()
1535 return Value.ToString ();
1538 public override object GetValue ()
1543 public override bool IsDefaultValue {
1549 public override bool IsNegative {
1555 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1557 if (target_type == TypeManager.byte_type) {
1558 if (in_checked_context){
1559 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1560 throw new OverflowException ();
1562 return new ByteConstant ((byte) Value, Location);
1564 if (target_type == TypeManager.sbyte_type) {
1565 if (in_checked_context){
1566 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1567 throw new OverflowException ();
1569 return new SByteConstant ((sbyte) Value, Location);
1571 if (target_type == TypeManager.short_type) {
1572 if (in_checked_context){
1573 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1574 throw new OverflowException ();
1576 return new ShortConstant ((short) Value, Location);
1578 if (target_type == TypeManager.ushort_type) {
1579 if (in_checked_context){
1580 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1581 throw new OverflowException ();
1583 return new UShortConstant ((ushort) Value, Location);
1585 if (target_type == TypeManager.int32_type) {
1586 if (in_checked_context){
1587 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1588 throw new OverflowException ();
1590 return new IntConstant ((int) Value, Location);
1592 if (target_type == TypeManager.uint32_type) {
1593 if (in_checked_context){
1594 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1595 throw new OverflowException ();
1597 return new UIntConstant ((uint) Value, Location);
1599 if (target_type == TypeManager.int64_type) {
1600 if (in_checked_context){
1601 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1602 throw new OverflowException ();
1604 return new LongConstant ((long) Value, Location);
1606 if (target_type == TypeManager.uint64_type) {
1607 if (in_checked_context){
1608 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1609 throw new OverflowException ();
1611 return new ULongConstant ((ulong) Value, Location);
1613 if (target_type == TypeManager.double_type)
1614 return new DoubleConstant ((double) Value, Location);
1615 if (target_type == TypeManager.char_type) {
1616 if (in_checked_context){
1617 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1618 throw new OverflowException ();
1620 return new CharConstant ((char) Value, Location);
1622 if (target_type == TypeManager.decimal_type)
1623 return new DecimalConstant ((decimal) Value, Location);
1630 public class DoubleConstant : Constant {
1631 public double Value;
1633 public DoubleConstant (double v, Location loc):
1639 protected override Expression DoResolve (ResolveContext rc)
1641 type = TypeManager.double_type;
1642 eclass = ExprClass.Value;
1646 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1648 enc.Stream.Write (Value);
1651 public override void Emit (EmitContext ec)
1653 ec.Emit (OpCodes.Ldc_R8, Value);
1656 public override string AsString ()
1658 return Value.ToString ();
1661 public override object GetValue ()
1666 public override bool IsDefaultValue {
1672 public override bool IsNegative {
1678 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1680 if (target_type == TypeManager.byte_type) {
1681 if (in_checked_context){
1682 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1683 throw new OverflowException ();
1685 return new ByteConstant ((byte) Value, Location);
1687 if (target_type == TypeManager.sbyte_type) {
1688 if (in_checked_context){
1689 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1690 throw new OverflowException ();
1692 return new SByteConstant ((sbyte) Value, Location);
1694 if (target_type == TypeManager.short_type) {
1695 if (in_checked_context){
1696 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1697 throw new OverflowException ();
1699 return new ShortConstant ((short) Value, Location);
1701 if (target_type == TypeManager.ushort_type) {
1702 if (in_checked_context){
1703 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1704 throw new OverflowException ();
1706 return new UShortConstant ((ushort) Value, Location);
1708 if (target_type == TypeManager.int32_type) {
1709 if (in_checked_context){
1710 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1711 throw new OverflowException ();
1713 return new IntConstant ((int) Value, Location);
1715 if (target_type == TypeManager.uint32_type) {
1716 if (in_checked_context){
1717 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1718 throw new OverflowException ();
1720 return new UIntConstant ((uint) Value, Location);
1722 if (target_type == TypeManager.int64_type) {
1723 if (in_checked_context){
1724 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1725 throw new OverflowException ();
1727 return new LongConstant ((long) Value, Location);
1729 if (target_type == TypeManager.uint64_type) {
1730 if (in_checked_context){
1731 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1732 throw new OverflowException ();
1734 return new ULongConstant ((ulong) Value, Location);
1736 if (target_type == TypeManager.float_type)
1737 return new FloatConstant ((float) Value, Location);
1738 if (target_type == TypeManager.char_type) {
1739 if (in_checked_context){
1740 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1741 throw new OverflowException ();
1743 return new CharConstant ((char) Value, Location);
1745 if (target_type == TypeManager.decimal_type)
1746 return new DecimalConstant ((decimal) Value, Location);
1753 public class DecimalConstant : Constant {
1754 public readonly decimal Value;
1756 public DecimalConstant (decimal d, Location loc):
1762 override public string AsString ()
1764 return Value.ToString () + "M";
1767 protected override Expression DoResolve (ResolveContext rc)
1769 type = TypeManager.decimal_type;
1770 eclass = ExprClass.Value;
1774 public override object GetValue ()
1776 return (object) Value;
1779 public override void Emit (EmitContext ec)
1781 int [] words = decimal.GetBits (Value);
1782 int power = (words [3] >> 16) & 0xff;
1785 if (Value <= int.MaxValue && Value >= int.MinValue) {
1786 if (TypeManager.void_decimal_ctor_int_arg == null) {
1787 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1788 TypeManager.decimal_type, loc, TypeManager.int32_type);
1790 if (TypeManager.void_decimal_ctor_int_arg == null)
1794 ec.EmitInt ((int) Value);
1795 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1799 if (Value <= long.MaxValue && Value >= long.MinValue) {
1800 if (TypeManager.void_decimal_ctor_long_arg == null) {
1801 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1802 TypeManager.decimal_type, loc, TypeManager.int64_type);
1804 if (TypeManager.void_decimal_ctor_long_arg == null)
1808 ec.EmitLong ((long) Value);
1809 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1814 ec.EmitInt (words [0]);
1815 ec.EmitInt (words [1]);
1816 ec.EmitInt (words [2]);
1819 ec.EmitInt (words [3] >> 31);
1824 if (TypeManager.void_decimal_ctor_five_args == null) {
1825 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1826 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1827 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1829 if (TypeManager.void_decimal_ctor_five_args == null)
1833 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1836 public override bool IsDefaultValue {
1842 public override bool IsNegative {
1848 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1850 if (target_type == TypeManager.sbyte_type)
1851 return new SByteConstant ((sbyte)Value, loc);
1852 if (target_type == TypeManager.byte_type)
1853 return new ByteConstant ((byte)Value, loc);
1854 if (target_type == TypeManager.short_type)
1855 return new ShortConstant ((short)Value, loc);
1856 if (target_type == TypeManager.ushort_type)
1857 return new UShortConstant ((ushort)Value, loc);
1858 if (target_type == TypeManager.int32_type)
1859 return new IntConstant ((int)Value, loc);
1860 if (target_type == TypeManager.uint32_type)
1861 return new UIntConstant ((uint)Value, loc);
1862 if (target_type == TypeManager.int64_type)
1863 return new LongConstant ((long)Value, loc);
1864 if (target_type == TypeManager.uint64_type)
1865 return new ULongConstant ((ulong)Value, loc);
1866 if (target_type == TypeManager.char_type)
1867 return new CharConstant ((char)Value, loc);
1868 if (target_type == TypeManager.float_type)
1869 return new FloatConstant ((float)Value, loc);
1870 if (target_type == TypeManager.double_type)
1871 return new DoubleConstant ((double)Value, loc);
1878 public class StringConstant : Constant {
1879 public readonly string Value;
1881 public StringConstant (string s, Location loc):
1887 // FIXME: Escape the string.
1888 override public string AsString ()
1890 return "\"" + Value + "\"";
1893 protected override Expression DoResolve (ResolveContext rc)
1895 type = TypeManager.string_type;
1896 eclass = ExprClass.Value;
1900 public override object GetValue ()
1905 public override void Emit (EmitContext ec)
1907 if (Value == null) {
1908 ec.Emit (OpCodes.Ldnull);
1913 // Use string.Empty for both literals and constants even if
1914 // it's not allowed at language level
1916 if (Value.Length == 0 && RootContext.Optimize && ec.CurrentType != TypeManager.string_type) {
1917 if (TypeManager.string_empty == null)
1918 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type);
1920 if (TypeManager.string_empty != null) {
1921 ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1926 ec.Emit (OpCodes.Ldstr, Value);
1929 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1932 if (type != targetType)
1938 public override bool IsDefaultValue {
1940 return Value == null;
1944 public override bool IsNegative {
1950 public override bool IsNull {
1952 return IsDefaultValue;
1956 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1963 // Null constant can have its own type, think of `default (Foo)'
1965 public class NullConstant : Constant
1967 public NullConstant (TypeSpec type, Location loc)
1970 eclass = ExprClass.Value;
1974 public override string AsString ()
1976 return GetSignatureForError ();
1979 public override Expression CreateExpressionTree (ResolveContext ec)
1981 if (type == InternalType.Null || type == TypeManager.object_type) {
1982 // Optimized version, also avoids referencing literal internal type
1983 Arguments args = new Arguments (1);
1984 args.Add (new Argument (this));
1985 return CreateExpressionFactoryCall (ec, "Constant", args);
1988 return base.CreateExpressionTree (ec);
1991 protected override Expression DoResolve (ResolveContext ec)
1996 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1998 // Type it as string cast
1999 if (targetType == TypeManager.object_type || targetType == InternalType.Null)
2000 enc.Encode (TypeManager.string_type);
2002 var ac = targetType as ArrayContainer;
2004 if (ac.Rank != 1 || ac.Element.IsArray)
2005 base.EncodeAttributeValue (rc, enc, targetType);
2007 enc.Stream.Write (uint.MaxValue);
2009 enc.Stream.Write (byte.MaxValue);
2013 public override void Emit (EmitContext ec)
2015 ec.Emit (OpCodes.Ldnull);
2017 // Only to make verifier happy
2018 if (TypeManager.IsGenericParameter (type))
2019 ec.Emit (OpCodes.Unbox_Any, type);
2022 public override string ExprClassName {
2024 return GetSignatureForError ();
2028 public override string GetSignatureForError ()
2033 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2035 if (targetType.IsPointer) {
2036 if (IsLiteral || this is NullPointer)
2037 return new EmptyConstantCast (new NullPointer (loc), targetType);
2042 // Exlude internal compiler types
2043 if (targetType.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null)
2046 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2049 if (TypeManager.IsReferenceType (targetType))
2050 return new NullConstant (targetType, loc);
2052 if (TypeManager.IsNullableType (targetType))
2053 return Nullable.LiftedNull.Create (targetType, loc);
2058 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
2060 return ConvertExplicitly (false, targetType);
2063 public override object GetValue ()
2068 public override bool IsDefaultValue {
2069 get { return true; }
2072 public override bool IsNegative {
2073 get { return false; }
2076 public override bool IsNull {
2077 get { return true; }
2080 public override bool IsZeroInteger {
2081 get { return true; }
2086 /// The value is constant, but when emitted has a side effect. This is
2087 /// used by BitwiseAnd to ensure that the second expression is invoked
2088 /// regardless of the value of the left side.
2090 public class SideEffectConstant : Constant {
2091 public Constant value;
2092 Expression side_effect;
2094 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2097 while (side_effect is SideEffectConstant)
2098 side_effect = ((SideEffectConstant) side_effect).side_effect;
2099 this.side_effect = side_effect;
2102 public override string AsString ()
2104 return value.AsString ();
2107 protected override Expression DoResolve (ResolveContext rc)
2109 value = value.Resolve (rc);
2112 eclass = ExprClass.Value;
2116 public override object GetValue ()
2118 return value.GetValue ();
2121 public override void Emit (EmitContext ec)
2123 side_effect.EmitSideEffect (ec);
2127 public override void EmitSideEffect (EmitContext ec)
2129 side_effect.EmitSideEffect (ec);
2130 value.EmitSideEffect (ec);
2133 public override bool IsDefaultValue {
2134 get { return value.IsDefaultValue; }
2137 public override bool IsNegative {
2138 get { return value.IsNegative; }
2141 public override bool IsZeroInteger {
2142 get { return value.IsZeroInteger; }
2145 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2147 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2148 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);