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.
13 using System.Reflection.Emit;
15 namespace Mono.CSharp {
18 /// Base class for constants and literals.
20 public abstract class Constant : Expression {
22 protected Constant (Location loc)
28 /// This is different from ToString in that ToString
29 /// is supposed to be there for debugging purposes,
30 /// and is not guaranteed to be useful for anything else,
31 /// AsString() will provide something that can be used
32 /// for round-tripping C# code. Maybe it can be used
33 /// for IL assembly as well.
35 public abstract string AsString ();
37 override public string ToString ()
39 return this.GetType ().Name + " (" + AsString () + ")";
43 /// This is used to obtain the actual value of the literal
44 /// cast into an object.
46 public abstract object GetValue ();
48 public virtual object GetTypedValue ()
53 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
55 if (!expl && IsLiteral &&
56 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
57 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
58 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
59 AsString (), TypeManager.CSharpName (target));
61 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
65 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
67 Constant c = ConvertImplicitly (ec, type);
69 Error_ValueCannotBeConverted (ec, loc, type, false);
74 public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
76 if (this.type == type)
79 if (Convert.ImplicitNumericConversion (this, type) == null)
83 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
86 // We should always catch the error before this is ever
87 // reached, by calling Convert.ImplicitStandardConversionExists
89 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
90 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
93 return CreateConstant (rc, type, constant_value, loc);
97 // Returns a constant instance based on Type
99 public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc)
101 return CreateConstantFromValue (t, v, loc).Resolve (rc);
104 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
106 if (t == TypeManager.int32_type)
107 return new IntConstant ((int) v, loc);
108 if (t == TypeManager.string_type)
109 return new StringConstant ((string) v, loc);
110 if (t == TypeManager.uint32_type)
111 return new UIntConstant ((uint) v, loc);
112 if (t == TypeManager.int64_type)
113 return new LongConstant ((long) v, loc);
114 if (t == TypeManager.uint64_type)
115 return new ULongConstant ((ulong) v, loc);
116 if (t == TypeManager.float_type)
117 return new FloatConstant ((float) v, loc);
118 if (t == TypeManager.double_type)
119 return new DoubleConstant ((double) v, loc);
120 if (t == TypeManager.short_type)
121 return new ShortConstant ((short)v, loc);
122 if (t == TypeManager.ushort_type)
123 return new UShortConstant ((ushort)v, loc);
124 if (t == TypeManager.sbyte_type)
125 return new SByteConstant ((sbyte)v, loc);
126 if (t == TypeManager.byte_type)
127 return new ByteConstant ((byte)v, loc);
128 if (t == TypeManager.char_type)
129 return new CharConstant ((char)v, loc);
130 if (t == TypeManager.bool_type)
131 return new BoolConstant ((bool) v, loc);
132 if (t == TypeManager.decimal_type)
133 return new DecimalConstant ((decimal) v, loc);
134 if (TypeManager.IsEnumType (t)) {
135 var real_type = EnumSpec.GetUnderlyingType (t);
136 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
139 if (TypeManager.IsNullableType (t))
140 return Nullable.LiftedNull.Create (t, loc);
142 if (TypeManager.IsReferenceType (t))
143 return new NullConstant (t, loc);
146 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
147 v, TypeManager.CSharpName (t));
150 public override Expression CreateExpressionTree (ResolveContext ec)
152 Arguments args = new Arguments (2);
153 args.Add (new Argument (this));
154 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
156 return CreateExpressionFactoryCall (ec, "Constant", args);
161 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
162 /// It throws OverflowException
164 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
165 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
168 /// Attempts to do a compile-time folding of a constant cast.
170 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
173 return TryReduce (ec, target_type);
175 catch (OverflowException) {
176 if (ec.ConstantCheckState) {
177 ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
178 GetValue ().ToString (), TypeManager.CSharpName (target_type));
180 Error_ValueCannotBeConverted (ec, loc, target_type, false);
183 return New.Constantify (target_type).Resolve (ec);
187 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
189 if (Type == target_type)
193 if (TypeManager.IsEnumType (target_type)) {
194 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
198 return new EnumConstant (c, target_type).Resolve (ec);
201 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
209 /// Need to pass type as the constant can require a boxing
210 /// and in such case no optimization is possible
212 public bool IsDefaultInitializer (TypeSpec type)
215 return IsDefaultValue;
217 return this is NullLiteral;
220 public abstract bool IsDefaultValue {
224 public abstract bool IsNegative {
229 // When constant is declared as literal
231 public virtual bool IsLiteral {
232 get { return false; }
235 public virtual bool IsOneInteger {
236 get { return false; }
240 // Returns true iff 1) the stack type of this is one of Object,
241 // int32, int64 and 2) this == 0 or this == null.
243 public virtual bool IsZeroInteger {
244 get { return false; }
247 public override void EmitSideEffect (EmitContext ec)
252 public sealed override Expression Clone (CloneContext clonectx)
254 // No cloning is not needed for constants
258 protected override void CloneTo (CloneContext clonectx, Expression target)
260 throw new NotSupportedException ("should not be reached");
263 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
265 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
268 public new Constant Resolve (ResolveContext rc)
270 if (eclass != ExprClass.Unresolved)
273 // Resolved constant has to be still a constant
274 Constant c = (Constant) DoResolve (rc);
278 if ((c.eclass & ExprClass.Value) == 0) {
279 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
284 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
290 public abstract class IntegralConstant : Constant
292 protected IntegralConstant (Location loc) :
297 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
300 ConvertExplicitly (true, target);
301 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
305 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
306 GetValue ().ToString (), TypeManager.CSharpName (target));
310 public abstract Constant Increment ();
313 public class BoolConstant : Constant {
314 public readonly bool Value;
316 public BoolConstant (bool val, Location loc):
322 override public string AsString ()
324 return Value ? "true" : "false";
327 protected override Expression DoResolve (ResolveContext ec)
329 type = TypeManager.bool_type;
330 eclass = ExprClass.Value;
334 public override object GetValue ()
336 return (object) Value;
339 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
341 enc.Stream.Write (Value);
344 public override void Emit (EmitContext ec)
347 ec.Emit (OpCodes.Ldc_I4_1);
349 ec.Emit (OpCodes.Ldc_I4_0);
352 public override bool IsDefaultValue {
358 public override bool IsNegative {
364 public override bool IsZeroInteger {
365 get { return Value == false; }
368 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
375 public class ByteConstant : IntegralConstant {
376 public readonly byte Value;
378 public ByteConstant (byte v, Location loc):
384 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
386 enc.Stream.Write (Value);
389 public override void Emit (EmitContext ec)
394 public override string AsString ()
396 return Value.ToString ();
399 protected override Expression DoResolve (ResolveContext ec)
401 type = TypeManager.byte_type;
402 eclass = ExprClass.Value;
406 public override object GetValue ()
411 public override Constant Increment ()
413 return new ByteConstant (checked ((byte)(Value + 1)), loc);
416 public override bool IsDefaultValue {
422 public override bool IsOneInteger {
428 public override bool IsNegative {
434 public override bool IsZeroInteger {
435 get { return Value == 0; }
438 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
440 if (target_type == TypeManager.sbyte_type) {
441 if (in_checked_context){
442 if (Value > SByte.MaxValue)
443 throw new OverflowException ();
445 return new SByteConstant ((sbyte) Value, Location);
447 if (target_type == TypeManager.short_type)
448 return new ShortConstant ((short) Value, Location);
449 if (target_type == TypeManager.ushort_type)
450 return new UShortConstant ((ushort) Value, Location);
451 if (target_type == TypeManager.int32_type)
452 return new IntConstant ((int) Value, Location);
453 if (target_type == TypeManager.uint32_type)
454 return new UIntConstant ((uint) Value, Location);
455 if (target_type == TypeManager.int64_type)
456 return new LongConstant ((long) Value, Location);
457 if (target_type == TypeManager.uint64_type)
458 return new ULongConstant ((ulong) Value, Location);
459 if (target_type == TypeManager.float_type)
460 return new FloatConstant ((float) Value, Location);
461 if (target_type == TypeManager.double_type)
462 return new DoubleConstant ((double) Value, Location);
463 if (target_type == TypeManager.char_type)
464 return new CharConstant ((char) Value, Location);
465 if (target_type == TypeManager.decimal_type)
466 return new DecimalConstant ((decimal) Value, Location);
473 public class CharConstant : Constant {
474 public readonly char Value;
476 public CharConstant (char v, Location loc):
482 protected override Expression DoResolve (ResolveContext rc)
484 type = TypeManager.char_type;
485 eclass = ExprClass.Value;
489 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
491 enc.Stream.Write ((ushort) Value);
494 public override void Emit (EmitContext ec)
499 static string descape (char c)
525 return c.ToString ();
528 public override string AsString ()
530 return "\"" + descape (Value) + "\"";
533 public override object GetValue ()
538 public override bool IsDefaultValue {
544 public override bool IsNegative {
550 public override bool IsZeroInteger {
551 get { return Value == '\0'; }
554 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
556 if (target_type == TypeManager.byte_type) {
557 if (in_checked_context){
558 if (Value < Byte.MinValue || Value > Byte.MaxValue)
559 throw new OverflowException ();
561 return new ByteConstant ((byte) Value, Location);
563 if (target_type == TypeManager.sbyte_type) {
564 if (in_checked_context){
565 if (Value > SByte.MaxValue)
566 throw new OverflowException ();
568 return new SByteConstant ((sbyte) Value, Location);
570 if (target_type == TypeManager.short_type) {
571 if (in_checked_context){
572 if (Value > Int16.MaxValue)
573 throw new OverflowException ();
575 return new ShortConstant ((short) Value, Location);
577 if (target_type == TypeManager.int32_type)
578 return new IntConstant ((int) Value, Location);
579 if (target_type == TypeManager.uint32_type)
580 return new UIntConstant ((uint) Value, Location);
581 if (target_type == TypeManager.int64_type)
582 return new LongConstant ((long) Value, Location);
583 if (target_type == TypeManager.uint64_type)
584 return new ULongConstant ((ulong) Value, Location);
585 if (target_type == TypeManager.float_type)
586 return new FloatConstant ((float) Value, Location);
587 if (target_type == TypeManager.double_type)
588 return new DoubleConstant ((double) Value, Location);
589 if (target_type == TypeManager.decimal_type)
590 return new DecimalConstant ((decimal) Value, Location);
597 public class SByteConstant : IntegralConstant {
598 public readonly sbyte Value;
600 public SByteConstant (sbyte v, Location loc):
606 protected override Expression DoResolve (ResolveContext rc)
608 type = TypeManager.sbyte_type;
609 eclass = ExprClass.Value;
613 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
615 enc.Stream.Write (Value);
618 public override void Emit (EmitContext ec)
623 public override string AsString ()
625 return Value.ToString ();
628 public override object GetValue ()
633 public override Constant Increment ()
635 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
638 public override bool IsDefaultValue {
644 public override bool IsNegative {
650 public override bool IsOneInteger {
656 public override bool IsZeroInteger {
657 get { return Value == 0; }
660 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
662 if (target_type == TypeManager.byte_type) {
663 if (in_checked_context && Value < 0)
664 throw new OverflowException ();
665 return new ByteConstant ((byte) Value, Location);
667 if (target_type == TypeManager.short_type)
668 return new ShortConstant ((short) Value, Location);
669 if (target_type == TypeManager.ushort_type) {
670 if (in_checked_context && Value < 0)
671 throw new OverflowException ();
672 return new UShortConstant ((ushort) Value, Location);
673 } if (target_type == TypeManager.int32_type)
674 return new IntConstant ((int) Value, Location);
675 if (target_type == TypeManager.uint32_type) {
676 if (in_checked_context && Value < 0)
677 throw new OverflowException ();
678 return new UIntConstant ((uint) Value, Location);
679 } if (target_type == TypeManager.int64_type)
680 return new LongConstant ((long) Value, Location);
681 if (target_type == TypeManager.uint64_type) {
682 if (in_checked_context && Value < 0)
683 throw new OverflowException ();
684 return new ULongConstant ((ulong) Value, Location);
686 if (target_type == TypeManager.float_type)
687 return new FloatConstant ((float) Value, Location);
688 if (target_type == TypeManager.double_type)
689 return new DoubleConstant ((double) Value, Location);
690 if (target_type == TypeManager.char_type) {
691 if (in_checked_context && Value < 0)
692 throw new OverflowException ();
693 return new CharConstant ((char) Value, Location);
695 if (target_type == TypeManager.decimal_type)
696 return new DecimalConstant ((decimal) Value, Location);
703 public class ShortConstant : IntegralConstant {
704 public readonly short Value;
706 public ShortConstant (short v, Location loc):
712 protected override Expression DoResolve (ResolveContext rc)
714 type = TypeManager.short_type;
715 eclass = ExprClass.Value;
719 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
721 enc.Stream.Write (Value);
724 public override void Emit (EmitContext ec)
729 public override string AsString ()
731 return Value.ToString ();
734 public override object GetValue ()
739 public override Constant Increment ()
741 return new ShortConstant (checked((short)(Value + 1)), loc);
744 public override bool IsDefaultValue {
750 public override bool IsZeroInteger {
751 get { return Value == 0; }
754 public override bool IsNegative {
760 public override bool IsOneInteger {
766 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
768 if (target_type == TypeManager.byte_type) {
769 if (in_checked_context){
770 if (Value < Byte.MinValue || Value > Byte.MaxValue)
771 throw new OverflowException ();
773 return new ByteConstant ((byte) Value, Location);
775 if (target_type == TypeManager.sbyte_type) {
776 if (in_checked_context){
777 if (Value < SByte.MinValue || Value > SByte.MaxValue)
778 throw new OverflowException ();
780 return new SByteConstant ((sbyte) Value, Location);
782 if (target_type == TypeManager.ushort_type) {
783 if (in_checked_context && Value < 0)
784 throw new OverflowException ();
786 return new UShortConstant ((ushort) Value, Location);
788 if (target_type == TypeManager.int32_type)
789 return new IntConstant ((int) Value, Location);
790 if (target_type == TypeManager.uint32_type) {
791 if (in_checked_context && Value < 0)
792 throw new OverflowException ();
793 return new UIntConstant ((uint) Value, Location);
795 if (target_type == TypeManager.int64_type)
796 return new LongConstant ((long) Value, Location);
797 if (target_type == TypeManager.uint64_type) {
798 if (in_checked_context && Value < 0)
799 throw new OverflowException ();
800 return new ULongConstant ((ulong) Value, Location);
802 if (target_type == TypeManager.float_type)
803 return new FloatConstant ((float) Value, Location);
804 if (target_type == TypeManager.double_type)
805 return new DoubleConstant ((double) Value, Location);
806 if (target_type == TypeManager.char_type) {
807 if (in_checked_context){
808 if (Value < Char.MinValue)
809 throw new OverflowException ();
811 return new CharConstant ((char) Value, Location);
813 if (target_type == TypeManager.decimal_type)
814 return new DecimalConstant ((decimal) Value, Location);
821 public class UShortConstant : IntegralConstant {
822 public readonly ushort Value;
824 public UShortConstant (ushort v, Location loc):
830 protected override Expression DoResolve (ResolveContext rc)
832 type = TypeManager.ushort_type;
833 eclass = ExprClass.Value;
837 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
839 enc.Stream.Write (Value);
842 public override void Emit (EmitContext ec)
847 public override string AsString ()
849 return Value.ToString ();
852 public override object GetValue ()
857 public override Constant Increment ()
859 return new UShortConstant (checked((ushort)(Value + 1)), loc);
862 public override bool IsDefaultValue {
868 public override bool IsNegative {
874 public override bool IsOneInteger {
880 public override bool IsZeroInteger {
881 get { return Value == 0; }
884 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
886 if (target_type == TypeManager.byte_type) {
887 if (in_checked_context){
888 if (Value > Byte.MaxValue)
889 throw new OverflowException ();
891 return new ByteConstant ((byte) Value, Location);
893 if (target_type == TypeManager.sbyte_type) {
894 if (in_checked_context){
895 if (Value > SByte.MaxValue)
896 throw new OverflowException ();
898 return new SByteConstant ((sbyte) Value, Location);
900 if (target_type == TypeManager.short_type) {
901 if (in_checked_context){
902 if (Value > Int16.MaxValue)
903 throw new OverflowException ();
905 return new ShortConstant ((short) Value, Location);
907 if (target_type == TypeManager.int32_type)
908 return new IntConstant ((int) Value, Location);
909 if (target_type == TypeManager.uint32_type)
910 return new UIntConstant ((uint) Value, Location);
911 if (target_type == TypeManager.int64_type)
912 return new LongConstant ((long) Value, Location);
913 if (target_type == TypeManager.uint64_type)
914 return new ULongConstant ((ulong) Value, Location);
915 if (target_type == TypeManager.float_type)
916 return new FloatConstant ((float) Value, Location);
917 if (target_type == TypeManager.double_type)
918 return new DoubleConstant ((double) Value, Location);
919 if (target_type == TypeManager.char_type) {
920 if (in_checked_context){
921 if (Value > Char.MaxValue)
922 throw new OverflowException ();
924 return new CharConstant ((char) Value, Location);
926 if (target_type == TypeManager.decimal_type)
927 return new DecimalConstant ((decimal) Value, Location);
933 public class IntConstant : IntegralConstant {
934 public readonly int Value;
936 public IntConstant (int v, Location loc):
942 protected override Expression DoResolve (ResolveContext rc)
944 type = TypeManager.int32_type;
945 eclass = ExprClass.Value;
949 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
951 enc.Stream.Write (Value);
954 public override void Emit (EmitContext ec)
959 public override string AsString ()
961 return Value.ToString ();
964 public override object GetValue ()
969 public override Constant Increment ()
971 return new IntConstant (checked(Value + 1), loc);
974 public override bool IsDefaultValue {
980 public override bool IsNegative {
986 public override bool IsOneInteger {
992 public override bool IsZeroInteger {
993 get { return Value == 0; }
996 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
998 if (target_type == TypeManager.byte_type) {
999 if (in_checked_context){
1000 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1001 throw new OverflowException ();
1003 return new ByteConstant ((byte) Value, Location);
1005 if (target_type == TypeManager.sbyte_type) {
1006 if (in_checked_context){
1007 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1008 throw new OverflowException ();
1010 return new SByteConstant ((sbyte) Value, Location);
1012 if (target_type == TypeManager.short_type) {
1013 if (in_checked_context){
1014 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1015 throw new OverflowException ();
1017 return new ShortConstant ((short) Value, Location);
1019 if (target_type == TypeManager.ushort_type) {
1020 if (in_checked_context){
1021 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1022 throw new OverflowException ();
1024 return new UShortConstant ((ushort) Value, Location);
1026 if (target_type == TypeManager.uint32_type) {
1027 if (in_checked_context){
1028 if (Value < UInt32.MinValue)
1029 throw new OverflowException ();
1031 return new UIntConstant ((uint) Value, Location);
1033 if (target_type == TypeManager.int64_type)
1034 return new LongConstant ((long) Value, Location);
1035 if (target_type == TypeManager.uint64_type) {
1036 if (in_checked_context && Value < 0)
1037 throw new OverflowException ();
1038 return new ULongConstant ((ulong) Value, Location);
1040 if (target_type == TypeManager.float_type)
1041 return new FloatConstant ((float) Value, Location);
1042 if (target_type == TypeManager.double_type)
1043 return new DoubleConstant ((double) Value, Location);
1044 if (target_type == TypeManager.char_type) {
1045 if (in_checked_context){
1046 if (Value < Char.MinValue || Value > Char.MaxValue)
1047 throw new OverflowException ();
1049 return new CharConstant ((char) Value, Location);
1051 if (target_type == TypeManager.decimal_type)
1052 return new DecimalConstant ((decimal) Value, Location);
1057 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1059 if (this.type == type)
1062 Constant c = TryImplicitIntConversion (type);
1064 return c.Resolve (rc);
1066 return base.ConvertImplicitly (rc, type);
1070 /// Attempts to perform an implicit constant conversion of the IntConstant
1071 /// into a different data type using casts (See Implicit Constant
1072 /// Expression Conversions)
1074 Constant TryImplicitIntConversion (TypeSpec target_type)
1076 if (target_type == TypeManager.sbyte_type) {
1077 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1078 return new SByteConstant ((sbyte) Value, loc);
1080 else if (target_type == TypeManager.byte_type) {
1081 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1082 return new ByteConstant ((byte) Value, loc);
1084 else if (target_type == TypeManager.short_type) {
1085 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1086 return new ShortConstant ((short) Value, loc);
1088 else if (target_type == TypeManager.ushort_type) {
1089 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1090 return new UShortConstant ((ushort) Value, loc);
1092 else if (target_type == TypeManager.uint32_type) {
1094 return new UIntConstant ((uint) Value, loc);
1096 else if (target_type == TypeManager.uint64_type) {
1098 // we can optimize this case: a positive int32
1099 // always fits on a uint64. But we need an opcode
1103 return new ULongConstant ((ulong) Value, loc);
1105 else if (target_type == TypeManager.double_type)
1106 return new DoubleConstant ((double) Value, loc);
1107 else if (target_type == TypeManager.float_type)
1108 return new FloatConstant ((float) Value, loc);
1114 public class UIntConstant : IntegralConstant {
1115 public readonly uint Value;
1117 public UIntConstant (uint v, Location loc):
1123 protected override Expression DoResolve (ResolveContext rc)
1125 type = TypeManager.uint32_type;
1126 eclass = ExprClass.Value;
1130 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1132 enc.Stream.Write (Value);
1135 public override void Emit (EmitContext ec)
1137 ec.EmitInt (unchecked ((int) Value));
1140 public override string AsString ()
1142 return Value.ToString ();
1145 public override object GetValue ()
1150 public override Constant Increment ()
1152 return new UIntConstant (checked(Value + 1), loc);
1155 public override bool IsDefaultValue {
1161 public override bool IsNegative {
1167 public override bool IsOneInteger {
1173 public override bool IsZeroInteger {
1174 get { return Value == 0; }
1177 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1179 if (target_type == TypeManager.byte_type) {
1180 if (in_checked_context){
1181 if (Value < Char.MinValue || Value > Char.MaxValue)
1182 throw new OverflowException ();
1184 return new ByteConstant ((byte) Value, Location);
1186 if (target_type == TypeManager.sbyte_type) {
1187 if (in_checked_context){
1188 if (Value > SByte.MaxValue)
1189 throw new OverflowException ();
1191 return new SByteConstant ((sbyte) Value, Location);
1193 if (target_type == TypeManager.short_type) {
1194 if (in_checked_context){
1195 if (Value > Int16.MaxValue)
1196 throw new OverflowException ();
1198 return new ShortConstant ((short) Value, Location);
1200 if (target_type == TypeManager.ushort_type) {
1201 if (in_checked_context){
1202 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1203 throw new OverflowException ();
1205 return new UShortConstant ((ushort) Value, Location);
1207 if (target_type == TypeManager.int32_type) {
1208 if (in_checked_context){
1209 if (Value > Int32.MaxValue)
1210 throw new OverflowException ();
1212 return new IntConstant ((int) Value, Location);
1214 if (target_type == TypeManager.int64_type)
1215 return new LongConstant ((long) Value, Location);
1216 if (target_type == TypeManager.uint64_type)
1217 return new ULongConstant ((ulong) Value, Location);
1218 if (target_type == TypeManager.float_type)
1219 return new FloatConstant ((float) Value, Location);
1220 if (target_type == TypeManager.double_type)
1221 return new DoubleConstant ((double) Value, Location);
1222 if (target_type == TypeManager.char_type) {
1223 if (in_checked_context){
1224 if (Value < Char.MinValue || Value > Char.MaxValue)
1225 throw new OverflowException ();
1227 return new CharConstant ((char) Value, Location);
1229 if (target_type == TypeManager.decimal_type)
1230 return new DecimalConstant ((decimal) Value, Location);
1237 public class LongConstant : IntegralConstant {
1238 public readonly long Value;
1240 public LongConstant (long v, Location loc):
1246 protected override Expression DoResolve (ResolveContext rc)
1248 type = TypeManager.int64_type;
1249 eclass = ExprClass.Value;
1253 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1255 enc.Stream.Write (Value);
1258 public override void Emit (EmitContext ec)
1260 ec.EmitLong (Value);
1263 public override string AsString ()
1265 return Value.ToString ();
1268 public override object GetValue ()
1273 public override Constant Increment ()
1275 return new LongConstant (checked(Value + 1), loc);
1278 public override bool IsDefaultValue {
1284 public override bool IsNegative {
1290 public override bool IsOneInteger {
1296 public override bool IsZeroInteger {
1297 get { return Value == 0; }
1300 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1302 if (target_type == TypeManager.byte_type) {
1303 if (in_checked_context){
1304 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1305 throw new OverflowException ();
1307 return new ByteConstant ((byte) Value, Location);
1309 if (target_type == TypeManager.sbyte_type) {
1310 if (in_checked_context){
1311 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1312 throw new OverflowException ();
1314 return new SByteConstant ((sbyte) Value, Location);
1316 if (target_type == TypeManager.short_type) {
1317 if (in_checked_context){
1318 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1319 throw new OverflowException ();
1321 return new ShortConstant ((short) Value, Location);
1323 if (target_type == TypeManager.ushort_type) {
1324 if (in_checked_context){
1325 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1326 throw new OverflowException ();
1328 return new UShortConstant ((ushort) Value, Location);
1330 if (target_type == TypeManager.int32_type) {
1331 if (in_checked_context){
1332 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1333 throw new OverflowException ();
1335 return new IntConstant ((int) Value, Location);
1337 if (target_type == TypeManager.uint32_type) {
1338 if (in_checked_context){
1339 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1340 throw new OverflowException ();
1342 return new UIntConstant ((uint) Value, Location);
1344 if (target_type == TypeManager.uint64_type) {
1345 if (in_checked_context && Value < 0)
1346 throw new OverflowException ();
1347 return new ULongConstant ((ulong) Value, Location);
1349 if (target_type == TypeManager.float_type)
1350 return new FloatConstant ((float) Value, Location);
1351 if (target_type == TypeManager.double_type)
1352 return new DoubleConstant ((double) Value, Location);
1353 if (target_type == TypeManager.char_type) {
1354 if (in_checked_context){
1355 if (Value < Char.MinValue || Value > Char.MaxValue)
1356 throw new OverflowException ();
1358 return new CharConstant ((char) Value, Location);
1360 if (target_type == TypeManager.decimal_type)
1361 return new DecimalConstant ((decimal) Value, Location);
1366 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1368 if (Value >= 0 && type == TypeManager.uint64_type) {
1369 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1372 return base.ConvertImplicitly (rc, type);
1376 public class ULongConstant : IntegralConstant {
1377 public readonly ulong Value;
1379 public ULongConstant (ulong v, Location loc):
1385 protected override Expression DoResolve (ResolveContext rc)
1387 type = TypeManager.uint64_type;
1388 eclass = ExprClass.Value;
1392 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1394 enc.Stream.Write (Value);
1397 public override void Emit (EmitContext ec)
1399 ec.EmitLong (unchecked ((long) Value));
1402 public override string AsString ()
1404 return Value.ToString ();
1407 public override object GetValue ()
1412 public override Constant Increment ()
1414 return new ULongConstant (checked(Value + 1), loc);
1417 public override bool IsDefaultValue {
1423 public override bool IsNegative {
1429 public override bool IsOneInteger {
1435 public override bool IsZeroInteger {
1436 get { return Value == 0; }
1439 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1441 if (target_type == TypeManager.byte_type) {
1442 if (in_checked_context && Value > Byte.MaxValue)
1443 throw new OverflowException ();
1444 return new ByteConstant ((byte) Value, Location);
1446 if (target_type == TypeManager.sbyte_type) {
1447 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1448 throw new OverflowException ();
1449 return new SByteConstant ((sbyte) Value, Location);
1451 if (target_type == TypeManager.short_type) {
1452 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1453 throw new OverflowException ();
1454 return new ShortConstant ((short) Value, Location);
1456 if (target_type == TypeManager.ushort_type) {
1457 if (in_checked_context && Value > UInt16.MaxValue)
1458 throw new OverflowException ();
1459 return new UShortConstant ((ushort) Value, Location);
1461 if (target_type == TypeManager.int32_type) {
1462 if (in_checked_context && Value > UInt32.MaxValue)
1463 throw new OverflowException ();
1464 return new IntConstant ((int) Value, Location);
1466 if (target_type == TypeManager.uint32_type) {
1467 if (in_checked_context && Value > UInt32.MaxValue)
1468 throw new OverflowException ();
1469 return new UIntConstant ((uint) Value, Location);
1471 if (target_type == TypeManager.int64_type) {
1472 if (in_checked_context && Value > Int64.MaxValue)
1473 throw new OverflowException ();
1474 return new LongConstant ((long) Value, Location);
1476 if (target_type == TypeManager.float_type)
1477 return new FloatConstant ((float) Value, Location);
1478 if (target_type == TypeManager.double_type)
1479 return new DoubleConstant ((double) Value, Location);
1480 if (target_type == TypeManager.char_type) {
1481 if (in_checked_context && Value > Char.MaxValue)
1482 throw new OverflowException ();
1483 return new CharConstant ((char) Value, Location);
1485 if (target_type == TypeManager.decimal_type)
1486 return new DecimalConstant ((decimal) Value, Location);
1493 public class FloatConstant : Constant {
1496 public FloatConstant (float v, Location loc):
1502 protected override Expression DoResolve (ResolveContext rc)
1504 type = TypeManager.float_type;
1505 eclass = ExprClass.Value;
1509 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1511 enc.Stream.Write (Value);
1514 public override void Emit (EmitContext ec)
1516 ec.Emit (OpCodes.Ldc_R4, Value);
1519 public override string AsString ()
1521 return Value.ToString ();
1524 public override object GetValue ()
1529 public override bool IsDefaultValue {
1535 public override bool IsNegative {
1541 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1543 if (target_type == TypeManager.byte_type) {
1544 if (in_checked_context){
1545 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1546 throw new OverflowException ();
1548 return new ByteConstant ((byte) Value, Location);
1550 if (target_type == TypeManager.sbyte_type) {
1551 if (in_checked_context){
1552 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1553 throw new OverflowException ();
1555 return new SByteConstant ((sbyte) Value, Location);
1557 if (target_type == TypeManager.short_type) {
1558 if (in_checked_context){
1559 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1560 throw new OverflowException ();
1562 return new ShortConstant ((short) Value, Location);
1564 if (target_type == TypeManager.ushort_type) {
1565 if (in_checked_context){
1566 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1567 throw new OverflowException ();
1569 return new UShortConstant ((ushort) Value, Location);
1571 if (target_type == TypeManager.int32_type) {
1572 if (in_checked_context){
1573 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1574 throw new OverflowException ();
1576 return new IntConstant ((int) Value, Location);
1578 if (target_type == TypeManager.uint32_type) {
1579 if (in_checked_context){
1580 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1581 throw new OverflowException ();
1583 return new UIntConstant ((uint) Value, Location);
1585 if (target_type == TypeManager.int64_type) {
1586 if (in_checked_context){
1587 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1588 throw new OverflowException ();
1590 return new LongConstant ((long) Value, Location);
1592 if (target_type == TypeManager.uint64_type) {
1593 if (in_checked_context){
1594 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1595 throw new OverflowException ();
1597 return new ULongConstant ((ulong) Value, Location);
1599 if (target_type == TypeManager.double_type)
1600 return new DoubleConstant ((double) Value, Location);
1601 if (target_type == TypeManager.char_type) {
1602 if (in_checked_context){
1603 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1604 throw new OverflowException ();
1606 return new CharConstant ((char) Value, Location);
1608 if (target_type == TypeManager.decimal_type)
1609 return new DecimalConstant ((decimal) Value, Location);
1616 public class DoubleConstant : Constant {
1617 public double Value;
1619 public DoubleConstant (double v, Location loc):
1625 protected override Expression DoResolve (ResolveContext rc)
1627 type = TypeManager.double_type;
1628 eclass = ExprClass.Value;
1632 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1634 enc.Stream.Write (Value);
1637 public override void Emit (EmitContext ec)
1639 ec.Emit (OpCodes.Ldc_R8, Value);
1642 public override string AsString ()
1644 return Value.ToString ();
1647 public override object GetValue ()
1652 public override bool IsDefaultValue {
1658 public override bool IsNegative {
1664 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1666 if (target_type == TypeManager.byte_type) {
1667 if (in_checked_context){
1668 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1669 throw new OverflowException ();
1671 return new ByteConstant ((byte) Value, Location);
1673 if (target_type == TypeManager.sbyte_type) {
1674 if (in_checked_context){
1675 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1676 throw new OverflowException ();
1678 return new SByteConstant ((sbyte) Value, Location);
1680 if (target_type == TypeManager.short_type) {
1681 if (in_checked_context){
1682 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1683 throw new OverflowException ();
1685 return new ShortConstant ((short) Value, Location);
1687 if (target_type == TypeManager.ushort_type) {
1688 if (in_checked_context){
1689 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1690 throw new OverflowException ();
1692 return new UShortConstant ((ushort) Value, Location);
1694 if (target_type == TypeManager.int32_type) {
1695 if (in_checked_context){
1696 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1697 throw new OverflowException ();
1699 return new IntConstant ((int) Value, Location);
1701 if (target_type == TypeManager.uint32_type) {
1702 if (in_checked_context){
1703 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1704 throw new OverflowException ();
1706 return new UIntConstant ((uint) Value, Location);
1708 if (target_type == TypeManager.int64_type) {
1709 if (in_checked_context){
1710 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1711 throw new OverflowException ();
1713 return new LongConstant ((long) Value, Location);
1715 if (target_type == TypeManager.uint64_type) {
1716 if (in_checked_context){
1717 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1718 throw new OverflowException ();
1720 return new ULongConstant ((ulong) Value, Location);
1722 if (target_type == TypeManager.float_type)
1723 return new FloatConstant ((float) Value, Location);
1724 if (target_type == TypeManager.char_type) {
1725 if (in_checked_context){
1726 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1727 throw new OverflowException ();
1729 return new CharConstant ((char) Value, Location);
1731 if (target_type == TypeManager.decimal_type)
1732 return new DecimalConstant ((decimal) Value, Location);
1739 public class DecimalConstant : Constant {
1740 public readonly decimal Value;
1742 public DecimalConstant (decimal d, Location loc):
1748 override public string AsString ()
1750 return Value.ToString () + "M";
1753 protected override Expression DoResolve (ResolveContext rc)
1755 type = TypeManager.decimal_type;
1756 eclass = ExprClass.Value;
1760 public override object GetValue ()
1762 return (object) Value;
1765 public override void Emit (EmitContext ec)
1767 int [] words = decimal.GetBits (Value);
1768 int power = (words [3] >> 16) & 0xff;
1771 if (Value <= int.MaxValue && Value >= int.MinValue) {
1772 if (TypeManager.void_decimal_ctor_int_arg == null) {
1773 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1774 TypeManager.decimal_type, loc, TypeManager.int32_type);
1776 if (TypeManager.void_decimal_ctor_int_arg == null)
1780 ec.EmitInt ((int) Value);
1781 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1785 if (Value <= long.MaxValue && Value >= long.MinValue) {
1786 if (TypeManager.void_decimal_ctor_long_arg == null) {
1787 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1788 TypeManager.decimal_type, loc, TypeManager.int64_type);
1790 if (TypeManager.void_decimal_ctor_long_arg == null)
1794 ec.EmitLong ((long) Value);
1795 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1800 ec.EmitInt (words [0]);
1801 ec.EmitInt (words [1]);
1802 ec.EmitInt (words [2]);
1805 ec.EmitInt (words [3] >> 31);
1810 if (TypeManager.void_decimal_ctor_five_args == null) {
1811 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1812 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1813 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1815 if (TypeManager.void_decimal_ctor_five_args == null)
1819 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1822 public override bool IsDefaultValue {
1828 public override bool IsNegative {
1834 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1836 if (target_type == TypeManager.sbyte_type)
1837 return new SByteConstant ((sbyte)Value, loc);
1838 if (target_type == TypeManager.byte_type)
1839 return new ByteConstant ((byte)Value, loc);
1840 if (target_type == TypeManager.short_type)
1841 return new ShortConstant ((short)Value, loc);
1842 if (target_type == TypeManager.ushort_type)
1843 return new UShortConstant ((ushort)Value, loc);
1844 if (target_type == TypeManager.int32_type)
1845 return new IntConstant ((int)Value, loc);
1846 if (target_type == TypeManager.uint32_type)
1847 return new UIntConstant ((uint)Value, loc);
1848 if (target_type == TypeManager.int64_type)
1849 return new LongConstant ((long)Value, loc);
1850 if (target_type == TypeManager.uint64_type)
1851 return new ULongConstant ((ulong)Value, loc);
1852 if (target_type == TypeManager.char_type)
1853 return new CharConstant ((char)Value, loc);
1854 if (target_type == TypeManager.float_type)
1855 return new FloatConstant ((float)Value, loc);
1856 if (target_type == TypeManager.double_type)
1857 return new DoubleConstant ((double)Value, loc);
1864 public class StringConstant : Constant {
1865 public readonly string Value;
1867 public StringConstant (string s, Location loc):
1873 // FIXME: Escape the string.
1874 override public string AsString ()
1876 return "\"" + Value + "\"";
1879 protected override Expression DoResolve (ResolveContext rc)
1881 type = TypeManager.string_type;
1882 eclass = ExprClass.Value;
1886 public override object GetValue ()
1891 public override void Emit (EmitContext ec)
1893 if (Value == null) {
1894 ec.Emit (OpCodes.Ldnull);
1899 // Use string.Empty for both literals and constants even if
1900 // it's not allowed at language level
1902 if (Value.Length == 0 && RootContext.Optimize && ec.CurrentType != TypeManager.string_type) {
1903 if (TypeManager.string_empty == null)
1904 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type);
1906 if (TypeManager.string_empty != null) {
1907 ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1912 ec.Emit (OpCodes.Ldstr, Value);
1915 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1918 if (type != targetType)
1924 public override bool IsDefaultValue {
1926 return Value == null;
1930 public override bool IsNegative {
1936 public override bool IsNull {
1938 return IsDefaultValue;
1942 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1949 // Null constant can have its own type, think of `default (Foo)'
1951 public class NullConstant : Constant
1953 public NullConstant (TypeSpec type, Location loc)
1956 eclass = ExprClass.Value;
1960 public override string AsString ()
1962 return GetSignatureForError ();
1965 public override Expression CreateExpressionTree (ResolveContext ec)
1967 if (type == InternalType.Null || type == TypeManager.object_type) {
1968 // Optimized version, also avoids referencing literal internal type
1969 Arguments args = new Arguments (1);
1970 args.Add (new Argument (this));
1971 return CreateExpressionFactoryCall (ec, "Constant", args);
1974 return base.CreateExpressionTree (ec);
1977 protected override Expression DoResolve (ResolveContext ec)
1982 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1984 // Type it as string cast
1985 if (targetType == TypeManager.object_type || targetType == InternalType.Null)
1986 enc.Encode (TypeManager.string_type);
1988 var ac = targetType as ArrayContainer;
1990 if (ac.Rank != 1 || ac.Element.IsArray)
1991 base.EncodeAttributeValue (rc, enc, targetType);
1993 enc.Stream.Write (uint.MaxValue);
1995 enc.Stream.Write (byte.MaxValue);
1999 public override void Emit (EmitContext ec)
2001 ec.Emit (OpCodes.Ldnull);
2003 // Only to make verifier happy
2004 if (TypeManager.IsGenericParameter (type))
2005 ec.Emit (OpCodes.Unbox_Any, type);
2008 public override string ExprClassName {
2010 return GetSignatureForError ();
2014 public override string GetSignatureForError ()
2019 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2021 if (targetType.IsPointer) {
2022 if (IsLiteral || this is NullPointer)
2023 return new EmptyConstantCast (new NullPointer (loc), targetType);
2028 // Exlude internal compiler types
2029 if (targetType == InternalType.AnonymousMethod)
2032 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2035 if (TypeManager.IsReferenceType (targetType))
2036 return new NullConstant (targetType, loc);
2038 if (TypeManager.IsNullableType (targetType))
2039 return Nullable.LiftedNull.Create (targetType, loc);
2044 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
2046 return ConvertExplicitly (false, targetType);
2049 public override object GetValue ()
2054 public override bool IsDefaultValue {
2055 get { return true; }
2058 public override bool IsNegative {
2059 get { return false; }
2062 public override bool IsNull {
2063 get { return true; }
2066 public override bool IsZeroInteger {
2067 get { return true; }
2072 /// The value is constant, but when emitted has a side effect. This is
2073 /// used by BitwiseAnd to ensure that the second expression is invoked
2074 /// regardless of the value of the left side.
2076 public class SideEffectConstant : Constant {
2077 public Constant value;
2078 Expression side_effect;
2080 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2083 while (side_effect is SideEffectConstant)
2084 side_effect = ((SideEffectConstant) side_effect).side_effect;
2085 this.side_effect = side_effect;
2088 public override string AsString ()
2090 return value.AsString ();
2093 protected override Expression DoResolve (ResolveContext rc)
2095 value = value.Resolve (rc);
2098 eclass = ExprClass.Value;
2102 public override object GetValue ()
2104 return value.GetValue ();
2107 public override void Emit (EmitContext ec)
2109 side_effect.EmitSideEffect (ec);
2113 public override void EmitSideEffect (EmitContext ec)
2115 side_effect.EmitSideEffect (ec);
2116 value.EmitSideEffect (ec);
2119 public override bool IsDefaultValue {
2120 get { return value.IsDefaultValue; }
2123 public override bool IsNegative {
2124 get { return value.IsNegative; }
2127 public override bool IsZeroInteger {
2128 get { return value.IsZeroInteger; }
2131 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2133 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2134 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);