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.Globalization;
16 using IKVM.Reflection.Emit;
18 using System.Reflection.Emit;
21 namespace Mono.CSharp {
24 /// Base class for constants and literals.
26 public abstract class Constant : Expression
28 static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
30 protected Constant (Location loc)
35 override public string ToString ()
37 return this.GetType ().Name + " (" + GetValueAsLiteral () + ")";
41 /// This is used to obtain the actual value of the literal
42 /// cast into an object.
44 public abstract object GetValue ();
46 public abstract long GetValueAsLong ();
48 public abstract string GetValueAsLiteral ();
52 // Returns an object value which is typed to contant type
54 public virtual object GetTypedValue ()
60 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
62 if (!expl && IsLiteral &&
63 BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
64 BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) {
65 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
66 GetValueAsLiteral (), TypeManager.CSharpName (target));
68 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
72 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
74 Constant c = ConvertImplicitly (type);
76 Error_ValueCannotBeConverted (ec, loc, type, false);
81 public virtual Constant ConvertImplicitly (TypeSpec type)
83 if (this.type == type)
86 if (Convert.ImplicitNumericConversion (this, type) == null)
90 object constant_value = ChangeType (GetValue (), type, out fail);
93 // We should always catch the error before this is ever
94 // reached, by calling Convert.ImplicitStandardConversionExists
96 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
97 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
100 return CreateConstant (type, constant_value, loc);
104 // Returns a constant instance based on Type
106 public static Constant CreateConstant (TypeSpec t, object v, Location loc)
108 return CreateConstantFromValue (t, v, loc);
111 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
113 switch (t.BuiltinType) {
114 case BuiltinTypeSpec.Type.Int:
115 return new IntConstant (t, (int) v, loc);
116 case BuiltinTypeSpec.Type.String:
117 return new StringConstant (t, (string) v, loc);
118 case BuiltinTypeSpec.Type.UInt:
119 return new UIntConstant (t, (uint) v, loc);
120 case BuiltinTypeSpec.Type.Long:
121 return new LongConstant (t, (long) v, loc);
122 case BuiltinTypeSpec.Type.ULong:
123 return new ULongConstant (t, (ulong) v, loc);
124 case BuiltinTypeSpec.Type.Float:
125 return new FloatConstant (t, (float) v, loc);
126 case BuiltinTypeSpec.Type.Double:
127 return new DoubleConstant (t, (double) v, loc);
128 case BuiltinTypeSpec.Type.Short:
129 return new ShortConstant (t, (short) v, loc);
130 case BuiltinTypeSpec.Type.UShort:
131 return new UShortConstant (t, (ushort) v, loc);
132 case BuiltinTypeSpec.Type.SByte:
133 return new SByteConstant (t, (sbyte) v, loc);
134 case BuiltinTypeSpec.Type.Byte:
135 return new ByteConstant (t, (byte) v, loc);
136 case BuiltinTypeSpec.Type.Char:
137 return new CharConstant (t, (char) v, loc);
138 case BuiltinTypeSpec.Type.Bool:
139 return new BoolConstant (t, (bool) v, loc);
140 case BuiltinTypeSpec.Type.Decimal:
141 return new DecimalConstant (t, (decimal) v, loc);
145 var real_type = EnumSpec.GetUnderlyingType (t);
146 return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t);
150 if (t.IsNullableType)
151 return Nullable.LiftedNull.Create (t, loc);
153 if (TypeSpec.IsReferenceType (t))
154 return new NullConstant (t, loc);
157 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
158 v, TypeManager.CSharpName (t));
161 public override Expression CreateExpressionTree (ResolveContext ec)
163 Arguments args = new Arguments (2);
164 args.Add (new Argument (this));
165 args.Add (new Argument (new TypeOf (type, loc)));
167 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);
177 // This is a custom version of Convert.ChangeType() which works
178 // with the TypeBuilder defined types when compiling corlib.
179 static object ChangeType (object value, TypeSpec targetType, out bool error)
181 IConvertible convert_value = value as IConvertible;
183 if (convert_value == null) {
189 // We cannot rely on build-in type conversions as they are
190 // more limited than what C# supports.
191 // See char -> float/decimal/double conversion
195 switch (targetType.BuiltinType) {
196 case BuiltinTypeSpec.Type.Bool:
197 return convert_value.ToBoolean (nfi);
198 case BuiltinTypeSpec.Type.Byte:
199 return convert_value.ToByte (nfi);
200 case BuiltinTypeSpec.Type.Char:
201 return convert_value.ToChar (nfi);
202 case BuiltinTypeSpec.Type.Short:
203 return convert_value.ToInt16 (nfi);
204 case BuiltinTypeSpec.Type.Int:
205 return convert_value.ToInt32 (nfi);
206 case BuiltinTypeSpec.Type.Long:
207 return convert_value.ToInt64 (nfi);
208 case BuiltinTypeSpec.Type.SByte:
209 return convert_value.ToSByte (nfi);
210 case BuiltinTypeSpec.Type.Decimal:
211 if (convert_value.GetType () == typeof (char))
212 return (decimal) convert_value.ToInt32 (nfi);
213 return convert_value.ToDecimal (nfi);
214 case BuiltinTypeSpec.Type.Double:
215 if (convert_value.GetType () == typeof (char))
216 return (double) convert_value.ToInt32 (nfi);
217 return convert_value.ToDouble (nfi);
218 case BuiltinTypeSpec.Type.Float:
219 if (convert_value.GetType () == typeof (char))
220 return (float) convert_value.ToInt32 (nfi);
221 return convert_value.ToSingle (nfi);
222 case BuiltinTypeSpec.Type.String:
223 return convert_value.ToString (nfi);
224 case BuiltinTypeSpec.Type.UShort:
225 return convert_value.ToUInt16 (nfi);
226 case BuiltinTypeSpec.Type.UInt:
227 return convert_value.ToUInt32 (nfi);
228 case BuiltinTypeSpec.Type.ULong:
229 return convert_value.ToUInt64 (nfi);
230 case BuiltinTypeSpec.Type.Object:
240 protected override Expression DoResolve (ResolveContext rc)
246 /// Attempts to do a compile-time folding of a constant cast.
248 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
251 return TryReduce (ec, target_type);
253 catch (OverflowException) {
254 if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
255 ec.Report.Error (221, loc,
256 "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
257 GetValueAsLiteral (), target_type.GetSignatureForError ());
259 Error_ValueCannotBeConverted (ec, loc, target_type, false);
262 return New.Constantify (target_type, loc);
266 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
268 if (Type == target_type)
272 if (TypeManager.IsEnumType (target_type)) {
273 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
277 return new EnumConstant (c, target_type);
280 return ConvertExplicitly (ec.ConstantCheckState, target_type);
284 /// Need to pass type as the constant can require a boxing
285 /// and in such case no optimization is possible
287 public bool IsDefaultInitializer (TypeSpec type)
290 return IsDefaultValue;
292 return this is NullLiteral;
295 public abstract bool IsDefaultValue {
299 public abstract bool IsNegative {
304 // When constant is declared as literal
306 public virtual bool IsLiteral {
307 get { return false; }
310 public virtual bool IsOneInteger {
311 get { return false; }
314 public override bool IsSideEffectFree {
321 // Returns true iff 1) the stack type of this is one of Object,
322 // int32, int64 and 2) this == 0 or this == null.
324 public virtual bool IsZeroInteger {
325 get { return false; }
328 public override void EmitSideEffect (EmitContext ec)
333 public sealed override Expression Clone (CloneContext clonectx)
335 // No cloning is not needed for constants
339 protected override void CloneTo (CloneContext clonectx, Expression target)
341 throw new NotSupportedException ("should not be reached");
344 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
347 return base.MakeExpression (ctx);
349 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
353 public new bool Resolve (ResolveContext rc)
355 // It exists only as hint not to call Resolve on constants
360 public abstract class IntegralConstant : Constant
362 protected IntegralConstant (TypeSpec type, Location loc)
366 eclass = ExprClass.Value;
369 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
372 ConvertExplicitly (true, target);
373 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
377 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
378 GetValue ().ToString (), TypeManager.CSharpName (target));
382 public override string GetValueAsLiteral ()
384 return GetValue ().ToString ();
387 public abstract Constant Increment ();
390 public class BoolConstant : Constant {
391 public readonly bool Value;
393 public BoolConstant (BuiltinTypes types, bool val, Location loc)
394 : this (types.Bool, val, loc)
398 public BoolConstant (TypeSpec type, bool val, Location loc)
401 eclass = ExprClass.Value;
407 public override object GetValue ()
409 return (object) Value;
412 public override string GetValueAsLiteral ()
414 return Value ? "true" : "false";
417 public override long GetValueAsLong ()
419 return Value ? 1 : 0;
422 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
427 public override void Emit (EmitContext ec)
430 ec.Emit (OpCodes.Ldc_I4_1);
432 ec.Emit (OpCodes.Ldc_I4_0);
435 public override bool IsDefaultValue {
441 public override bool IsNegative {
447 public override bool IsZeroInteger {
448 get { return Value == false; }
451 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
458 public class ByteConstant : IntegralConstant
460 public readonly byte Value;
462 public ByteConstant (BuiltinTypes types, byte v, Location loc)
463 : this (types.Byte, v, loc)
467 public ByteConstant (TypeSpec type, byte v, Location loc)
473 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
478 public override void Emit (EmitContext ec)
483 public override object GetValue ()
488 public override long GetValueAsLong ()
493 public override Constant Increment ()
495 return new ByteConstant (type, checked ((byte)(Value + 1)), loc);
498 public override bool IsDefaultValue {
504 public override bool IsOneInteger {
510 public override bool IsNegative {
516 public override bool IsZeroInteger {
517 get { return Value == 0; }
520 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
522 switch (target_type.BuiltinType) {
523 case BuiltinTypeSpec.Type.SByte:
524 if (in_checked_context){
525 if (Value > SByte.MaxValue)
526 throw new OverflowException ();
528 return new SByteConstant (target_type, (sbyte) Value, Location);
529 case BuiltinTypeSpec.Type.Short:
530 return new ShortConstant (target_type, (short) Value, Location);
531 case BuiltinTypeSpec.Type.UShort:
532 return new UShortConstant (target_type, (ushort) Value, Location);
533 case BuiltinTypeSpec.Type.Int:
534 return new IntConstant (target_type, (int) Value, Location);
535 case BuiltinTypeSpec.Type.UInt:
536 return new UIntConstant (target_type, (uint) Value, Location);
537 case BuiltinTypeSpec.Type.Long:
538 return new LongConstant (target_type, (long) Value, Location);
539 case BuiltinTypeSpec.Type.ULong:
540 return new ULongConstant (target_type, (ulong) Value, Location);
541 case BuiltinTypeSpec.Type.Float:
542 return new FloatConstant (target_type, (float) Value, Location);
543 case BuiltinTypeSpec.Type.Double:
544 return new DoubleConstant (target_type, (double) Value, Location);
545 case BuiltinTypeSpec.Type.Char:
546 return new CharConstant (target_type, (char) Value, Location);
547 case BuiltinTypeSpec.Type.Decimal:
548 return new DecimalConstant (target_type, (decimal) Value, Location);
556 public class CharConstant : Constant {
557 public readonly char Value;
559 public CharConstant (BuiltinTypes types, char v, Location loc)
560 : this (types.Char, v, loc)
564 public CharConstant (TypeSpec type, char v, Location loc)
568 eclass = ExprClass.Value;
573 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
575 enc.Encode ((ushort) Value);
578 public override void Emit (EmitContext ec)
583 static string descape (char c)
609 return c.ToString ();
612 public override object GetValue ()
617 public override long GetValueAsLong ()
622 public override string GetValueAsLiteral ()
624 return "\"" + descape (Value) + "\"";
627 public override bool IsDefaultValue {
633 public override bool IsNegative {
639 public override bool IsZeroInteger {
640 get { return Value == '\0'; }
643 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
645 switch (target_type.BuiltinType) {
646 case BuiltinTypeSpec.Type.Byte:
647 if (in_checked_context) {
648 if (Value < Byte.MinValue || Value > Byte.MaxValue)
649 throw new OverflowException ();
651 return new ByteConstant (target_type, (byte) Value, Location);
652 case BuiltinTypeSpec.Type.SByte:
653 if (in_checked_context) {
654 if (Value > SByte.MaxValue)
655 throw new OverflowException ();
657 return new SByteConstant (target_type, (sbyte) Value, Location);
659 case BuiltinTypeSpec.Type.Short:
660 if (in_checked_context) {
661 if (Value > Int16.MaxValue)
662 throw new OverflowException ();
664 return new ShortConstant (target_type, (short) Value, Location);
665 case BuiltinTypeSpec.Type.Int:
666 return new IntConstant (target_type, (int) Value, Location);
667 case BuiltinTypeSpec.Type.UInt:
668 return new UIntConstant (target_type, (uint) Value, Location);
669 case BuiltinTypeSpec.Type.Long:
670 return new LongConstant (target_type, (long) Value, Location);
671 case BuiltinTypeSpec.Type.ULong:
672 return new ULongConstant (target_type, (ulong) Value, Location);
673 case BuiltinTypeSpec.Type.Float:
674 return new FloatConstant (target_type, (float) Value, Location);
675 case BuiltinTypeSpec.Type.Double:
676 return new DoubleConstant (target_type, (double) Value, Location);
677 case BuiltinTypeSpec.Type.Decimal:
678 return new DecimalConstant (target_type, (decimal) Value, Location);
686 public class SByteConstant : IntegralConstant
688 public readonly sbyte Value;
690 public SByteConstant (BuiltinTypes types, sbyte v, Location loc)
691 : this (types.SByte, v, loc)
695 public SByteConstant (TypeSpec type, sbyte v, Location loc)
701 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
706 public override void Emit (EmitContext ec)
711 public override object GetValue ()
716 public override long GetValueAsLong ()
721 public override Constant Increment ()
723 return new SByteConstant (type, checked((sbyte)(Value + 1)), loc);
726 public override bool IsDefaultValue {
732 public override bool IsNegative {
738 public override bool IsOneInteger {
744 public override bool IsZeroInteger {
745 get { return Value == 0; }
748 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
750 switch (target_type.BuiltinType) {
751 case BuiltinTypeSpec.Type.Byte:
752 if (in_checked_context && Value < 0)
753 throw new OverflowException ();
754 return new ByteConstant (target_type, (byte) Value, Location);
755 case BuiltinTypeSpec.Type.Short:
756 return new ShortConstant (target_type, (short) Value, Location);
757 case BuiltinTypeSpec.Type.UShort:
758 if (in_checked_context && Value < 0)
759 throw new OverflowException ();
760 return new UShortConstant (target_type, (ushort) Value, Location);
761 case BuiltinTypeSpec.Type.Int:
762 return new IntConstant (target_type, (int) Value, Location);
763 case BuiltinTypeSpec.Type.UInt:
764 if (in_checked_context && Value < 0)
765 throw new OverflowException ();
766 return new UIntConstant (target_type, (uint) Value, Location);
767 case BuiltinTypeSpec.Type.Long:
768 return new LongConstant (target_type, (long) Value, Location);
769 case BuiltinTypeSpec.Type.ULong:
770 if (in_checked_context && Value < 0)
771 throw new OverflowException ();
772 return new ULongConstant (target_type, (ulong) Value, Location);
773 case BuiltinTypeSpec.Type.Float:
774 return new FloatConstant (target_type, (float) Value, Location);
775 case BuiltinTypeSpec.Type.Double:
776 return new DoubleConstant (target_type, (double) Value, Location);
777 case BuiltinTypeSpec.Type.Char:
778 if (in_checked_context && Value < 0)
779 throw new OverflowException ();
780 return new CharConstant (target_type, (char) Value, Location);
781 case BuiltinTypeSpec.Type.Decimal:
782 return new DecimalConstant (target_type, (decimal) Value, Location);
790 public class ShortConstant : IntegralConstant {
791 public readonly short Value;
793 public ShortConstant (BuiltinTypes types, short v, Location loc)
794 : this (types.Short, v, loc)
798 public ShortConstant (TypeSpec type, short v, Location loc)
804 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
809 public override void Emit (EmitContext ec)
814 public override object GetValue ()
819 public override long GetValueAsLong ()
824 public override Constant Increment ()
826 return new ShortConstant (type, checked((short)(Value + 1)), loc);
829 public override bool IsDefaultValue {
835 public override bool IsZeroInteger {
836 get { return Value == 0; }
839 public override bool IsNegative {
845 public override bool IsOneInteger {
851 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
853 switch (target_type.BuiltinType) {
854 case BuiltinTypeSpec.Type.Byte:
855 if (in_checked_context) {
856 if (Value < Byte.MinValue || Value > Byte.MaxValue)
857 throw new OverflowException ();
859 return new ByteConstant (target_type, (byte) Value, Location);
860 case BuiltinTypeSpec.Type.SByte:
861 if (in_checked_context) {
862 if (Value < SByte.MinValue || Value > SByte.MaxValue)
863 throw new OverflowException ();
865 return new SByteConstant (target_type, (sbyte) Value, Location);
866 case BuiltinTypeSpec.Type.UShort:
867 if (in_checked_context && Value < 0)
868 throw new OverflowException ();
870 return new UShortConstant (target_type, (ushort) Value, Location);
871 case BuiltinTypeSpec.Type.Int:
872 return new IntConstant (target_type, (int) Value, Location);
873 case BuiltinTypeSpec.Type.UInt:
874 if (in_checked_context && Value < 0)
875 throw new OverflowException ();
876 return new UIntConstant (target_type, (uint) Value, Location);
877 case BuiltinTypeSpec.Type.Long:
878 return new LongConstant (target_type, (long) Value, Location);
879 case BuiltinTypeSpec.Type.ULong:
880 if (in_checked_context && Value < 0)
881 throw new OverflowException ();
882 return new ULongConstant (target_type, (ulong) Value, Location);
883 case BuiltinTypeSpec.Type.Float:
884 return new FloatConstant (target_type, (float) Value, Location);
885 case BuiltinTypeSpec.Type.Double:
886 return new DoubleConstant (target_type, (double) Value, Location);
887 case BuiltinTypeSpec.Type.Char:
888 if (in_checked_context) {
889 if (Value < Char.MinValue)
890 throw new OverflowException ();
892 return new CharConstant (target_type, (char) Value, Location);
893 case BuiltinTypeSpec.Type.Decimal:
894 return new DecimalConstant (target_type, (decimal) Value, Location);
902 public class UShortConstant : IntegralConstant
904 public readonly ushort Value;
906 public UShortConstant (BuiltinTypes types, ushort v, Location loc)
907 : this (types.UShort, v, loc)
911 public UShortConstant (TypeSpec type, ushort v, Location loc)
917 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
922 public override void Emit (EmitContext ec)
927 public override object GetValue ()
932 public override long GetValueAsLong ()
937 public override Constant Increment ()
939 return new UShortConstant (type, checked((ushort)(Value + 1)), loc);
942 public override bool IsDefaultValue {
948 public override bool IsNegative {
954 public override bool IsOneInteger {
960 public override bool IsZeroInteger {
961 get { return Value == 0; }
964 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
966 switch (target_type.BuiltinType) {
967 case BuiltinTypeSpec.Type.Byte:
968 if (in_checked_context) {
969 if (Value > Byte.MaxValue)
970 throw new OverflowException ();
972 return new ByteConstant (target_type, (byte) Value, Location);
973 case BuiltinTypeSpec.Type.SByte:
974 if (in_checked_context) {
975 if (Value > SByte.MaxValue)
976 throw new OverflowException ();
978 return new SByteConstant (target_type, (sbyte) Value, Location);
979 case BuiltinTypeSpec.Type.Short:
980 if (in_checked_context) {
981 if (Value > Int16.MaxValue)
982 throw new OverflowException ();
984 return new ShortConstant (target_type, (short) Value, Location);
985 case BuiltinTypeSpec.Type.Int:
986 return new IntConstant (target_type, (int) Value, Location);
987 case BuiltinTypeSpec.Type.UInt:
988 return new UIntConstant (target_type, (uint) Value, Location);
989 case BuiltinTypeSpec.Type.Long:
990 return new LongConstant (target_type, (long) Value, Location);
991 case BuiltinTypeSpec.Type.ULong:
992 return new ULongConstant (target_type, (ulong) Value, Location);
993 case BuiltinTypeSpec.Type.Float:
994 return new FloatConstant (target_type, (float) Value, Location);
995 case BuiltinTypeSpec.Type.Double:
996 return new DoubleConstant (target_type, (double) Value, Location);
997 case BuiltinTypeSpec.Type.Char:
998 if (in_checked_context) {
999 if (Value > Char.MaxValue)
1000 throw new OverflowException ();
1002 return new CharConstant (target_type, (char) Value, Location);
1003 case BuiltinTypeSpec.Type.Decimal:
1004 return new DecimalConstant (target_type, (decimal) Value, Location);
1011 public class IntConstant : IntegralConstant
1013 public readonly int Value;
1015 public IntConstant (BuiltinTypes types, int v, Location loc)
1016 : this (types.Int, v, loc)
1020 public IntConstant (TypeSpec type, int v, Location loc)
1026 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1031 public override void Emit (EmitContext ec)
1036 public override object GetValue ()
1041 public override long GetValueAsLong ()
1046 public override Constant Increment ()
1048 return new IntConstant (type, checked(Value + 1), loc);
1051 public override bool IsDefaultValue {
1057 public override bool IsNegative {
1063 public override bool IsOneInteger {
1069 public override bool IsZeroInteger {
1070 get { return Value == 0; }
1073 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1075 switch (target_type.BuiltinType) {
1076 case BuiltinTypeSpec.Type.Byte:
1077 if (in_checked_context) {
1078 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1079 throw new OverflowException ();
1081 return new ByteConstant (target_type, (byte) Value, Location);
1082 case BuiltinTypeSpec.Type.SByte:
1083 if (in_checked_context) {
1084 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1085 throw new OverflowException ();
1087 return new SByteConstant (target_type, (sbyte) Value, Location);
1088 case BuiltinTypeSpec.Type.Short:
1089 if (in_checked_context) {
1090 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1091 throw new OverflowException ();
1093 return new ShortConstant (target_type, (short) Value, Location);
1094 case BuiltinTypeSpec.Type.UShort:
1095 if (in_checked_context) {
1096 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1097 throw new OverflowException ();
1099 return new UShortConstant (target_type, (ushort) Value, Location);
1100 case BuiltinTypeSpec.Type.UInt:
1101 if (in_checked_context) {
1102 if (Value < UInt32.MinValue)
1103 throw new OverflowException ();
1105 return new UIntConstant (target_type, (uint) Value, Location);
1106 case BuiltinTypeSpec.Type.Long:
1107 return new LongConstant (target_type, (long) Value, Location);
1108 case BuiltinTypeSpec.Type.ULong:
1109 if (in_checked_context && Value < 0)
1110 throw new OverflowException ();
1111 return new ULongConstant (target_type, (ulong) Value, Location);
1112 case BuiltinTypeSpec.Type.Float:
1113 return new FloatConstant (target_type, (float) Value, Location);
1114 case BuiltinTypeSpec.Type.Double:
1115 return new DoubleConstant (target_type, (double) Value, Location);
1116 case BuiltinTypeSpec.Type.Char:
1117 if (in_checked_context) {
1118 if (Value < Char.MinValue || Value > Char.MaxValue)
1119 throw new OverflowException ();
1121 return new CharConstant (target_type, (char) Value, Location);
1122 case BuiltinTypeSpec.Type.Decimal:
1123 return new DecimalConstant (target_type, (decimal) Value, Location);
1129 public override Constant ConvertImplicitly (TypeSpec type)
1131 if (this.type == type)
1134 Constant c = TryImplicitIntConversion (type);
1136 return c; //.Resolve (rc);
1138 return base.ConvertImplicitly (type);
1142 /// Attempts to perform an implicit constant conversion of the IntConstant
1143 /// into a different data type using casts (See Implicit Constant
1144 /// Expression Conversions)
1146 Constant TryImplicitIntConversion (TypeSpec target_type)
1148 switch (target_type.BuiltinType) {
1149 case BuiltinTypeSpec.Type.SByte:
1150 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1151 return new SByteConstant (target_type, (sbyte) Value, loc);
1153 case BuiltinTypeSpec.Type.Byte:
1154 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1155 return new ByteConstant (target_type, (byte) Value, loc);
1157 case BuiltinTypeSpec.Type.Short:
1158 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1159 return new ShortConstant (target_type, (short) Value, loc);
1161 case BuiltinTypeSpec.Type.UShort:
1162 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1163 return new UShortConstant (target_type, (ushort) Value, loc);
1165 case BuiltinTypeSpec.Type.UInt:
1167 return new UIntConstant (target_type, (uint) Value, loc);
1169 case BuiltinTypeSpec.Type.ULong:
1171 // we can optimize this case: a positive int32
1172 // always fits on a uint64. But we need an opcode
1176 return new ULongConstant (target_type, (ulong) Value, loc);
1178 case BuiltinTypeSpec.Type.Double:
1179 return new DoubleConstant (target_type, (double) Value, loc);
1180 case BuiltinTypeSpec.Type.Float:
1181 return new FloatConstant (target_type, (float) Value, loc);
1188 public class UIntConstant : IntegralConstant {
1189 public readonly uint Value;
1191 public UIntConstant (BuiltinTypes types, uint v, Location loc)
1192 : this (types.UInt, v, loc)
1196 public UIntConstant (TypeSpec type, uint v, Location loc)
1202 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1207 public override void Emit (EmitContext ec)
1209 ec.EmitInt (unchecked ((int) Value));
1212 public override object GetValue ()
1217 public override long GetValueAsLong ()
1222 public override Constant Increment ()
1224 return new UIntConstant (type, checked(Value + 1), loc);
1227 public override bool IsDefaultValue {
1233 public override bool IsNegative {
1239 public override bool IsOneInteger {
1245 public override bool IsZeroInteger {
1246 get { return Value == 0; }
1249 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1251 switch (target_type.BuiltinType) {
1252 case BuiltinTypeSpec.Type.Byte:
1253 if (in_checked_context) {
1254 if (Value < 0 || Value > byte.MaxValue)
1255 throw new OverflowException ();
1257 return new ByteConstant (target_type, (byte) Value, Location);
1258 case BuiltinTypeSpec.Type.SByte:
1259 if (in_checked_context) {
1260 if (Value > SByte.MaxValue)
1261 throw new OverflowException ();
1263 return new SByteConstant (target_type, (sbyte) Value, Location);
1264 case BuiltinTypeSpec.Type.Short:
1265 if (in_checked_context) {
1266 if (Value > Int16.MaxValue)
1267 throw new OverflowException ();
1269 return new ShortConstant (target_type, (short) Value, Location);
1270 case BuiltinTypeSpec.Type.UShort:
1271 if (in_checked_context) {
1272 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1273 throw new OverflowException ();
1275 return new UShortConstant (target_type, (ushort) Value, Location);
1276 case BuiltinTypeSpec.Type.Int:
1277 if (in_checked_context) {
1278 if (Value > Int32.MaxValue)
1279 throw new OverflowException ();
1281 return new IntConstant (target_type, (int) Value, Location);
1282 case BuiltinTypeSpec.Type.Long:
1283 return new LongConstant (target_type, (long) Value, Location);
1284 case BuiltinTypeSpec.Type.ULong:
1285 return new ULongConstant (target_type, (ulong) Value, Location);
1286 case BuiltinTypeSpec.Type.Float:
1287 return new FloatConstant (target_type, (float) Value, Location);
1288 case BuiltinTypeSpec.Type.Double:
1289 return new DoubleConstant (target_type, (double) Value, Location);
1290 case BuiltinTypeSpec.Type.Char:
1291 if (in_checked_context) {
1292 if (Value < Char.MinValue || Value > Char.MaxValue)
1293 throw new OverflowException ();
1295 return new CharConstant (target_type, (char) Value, Location);
1296 case BuiltinTypeSpec.Type.Decimal:
1297 return new DecimalConstant (target_type, (decimal) Value, Location);
1305 public class LongConstant : IntegralConstant {
1306 public readonly long Value;
1308 public LongConstant (BuiltinTypes types, long v, Location loc)
1309 : this (types.Long, v, loc)
1313 public LongConstant (TypeSpec type, long v, Location loc)
1319 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1324 public override void Emit (EmitContext ec)
1326 ec.EmitLong (Value);
1329 public override object GetValue ()
1334 public override long GetValueAsLong ()
1339 public override Constant Increment ()
1341 return new LongConstant (type, checked(Value + 1), loc);
1344 public override bool IsDefaultValue {
1350 public override bool IsNegative {
1356 public override bool IsOneInteger {
1362 public override bool IsZeroInteger {
1363 get { return Value == 0; }
1366 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1368 switch (target_type.BuiltinType) {
1369 case BuiltinTypeSpec.Type.Byte:
1370 if (in_checked_context) {
1371 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1372 throw new OverflowException ();
1374 return new ByteConstant (target_type, (byte) Value, Location);
1375 case BuiltinTypeSpec.Type.SByte:
1376 if (in_checked_context) {
1377 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1378 throw new OverflowException ();
1380 return new SByteConstant (target_type, (sbyte) Value, Location);
1381 case BuiltinTypeSpec.Type.Short:
1382 if (in_checked_context) {
1383 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1384 throw new OverflowException ();
1386 return new ShortConstant (target_type, (short) Value, Location);
1387 case BuiltinTypeSpec.Type.UShort:
1388 if (in_checked_context) {
1389 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1390 throw new OverflowException ();
1392 return new UShortConstant (target_type, (ushort) Value, Location);
1393 case BuiltinTypeSpec.Type.Int:
1394 if (in_checked_context) {
1395 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1396 throw new OverflowException ();
1398 return new IntConstant (target_type, (int) Value, Location);
1399 case BuiltinTypeSpec.Type.UInt:
1400 if (in_checked_context) {
1401 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1402 throw new OverflowException ();
1404 return new UIntConstant (target_type, (uint) Value, Location);
1405 case BuiltinTypeSpec.Type.ULong:
1406 if (in_checked_context && Value < 0)
1407 throw new OverflowException ();
1408 return new ULongConstant (target_type, (ulong) Value, Location);
1409 case BuiltinTypeSpec.Type.Float:
1410 return new FloatConstant (target_type, (float) Value, Location);
1411 case BuiltinTypeSpec.Type.Double:
1412 return new DoubleConstant (target_type, (double) Value, Location);
1413 case BuiltinTypeSpec.Type.Char:
1414 if (in_checked_context) {
1415 if (Value < Char.MinValue || Value > Char.MaxValue)
1416 throw new OverflowException ();
1418 return new CharConstant (target_type, (char) Value, Location);
1419 case BuiltinTypeSpec.Type.Decimal:
1420 return new DecimalConstant (target_type, (decimal) Value, Location);
1426 public override Constant ConvertImplicitly (TypeSpec type)
1428 if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) {
1429 return new ULongConstant (type, (ulong) Value, loc);
1432 return base.ConvertImplicitly (type);
1436 public class ULongConstant : IntegralConstant {
1437 public readonly ulong Value;
1439 public ULongConstant (BuiltinTypes types, ulong v, Location loc)
1440 : this (types.ULong, v, loc)
1444 public ULongConstant (TypeSpec type, ulong v, Location loc)
1450 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1455 public override void Emit (EmitContext ec)
1457 ec.EmitLong (unchecked ((long) Value));
1460 public override object GetValue ()
1465 public override long GetValueAsLong ()
1467 return (long) Value;
1470 public override Constant Increment ()
1472 return new ULongConstant (type, checked(Value + 1), loc);
1475 public override bool IsDefaultValue {
1481 public override bool IsNegative {
1487 public override bool IsOneInteger {
1493 public override bool IsZeroInteger {
1494 get { return Value == 0; }
1497 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1499 switch (target_type.BuiltinType) {
1500 case BuiltinTypeSpec.Type.Byte:
1501 if (in_checked_context && Value > Byte.MaxValue)
1502 throw new OverflowException ();
1503 return new ByteConstant (target_type, (byte) Value, Location);
1504 case BuiltinTypeSpec.Type.SByte:
1505 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1506 throw new OverflowException ();
1507 return new SByteConstant (target_type, (sbyte) Value, Location);
1508 case BuiltinTypeSpec.Type.Short:
1509 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1510 throw new OverflowException ();
1511 return new ShortConstant (target_type, (short) Value, Location);
1512 case BuiltinTypeSpec.Type.UShort:
1513 if (in_checked_context && Value > UInt16.MaxValue)
1514 throw new OverflowException ();
1515 return new UShortConstant (target_type, (ushort) Value, Location);
1516 case BuiltinTypeSpec.Type.Int:
1517 if (in_checked_context && Value > UInt32.MaxValue)
1518 throw new OverflowException ();
1519 return new IntConstant (target_type, (int) Value, Location);
1520 case BuiltinTypeSpec.Type.UInt:
1521 if (in_checked_context && Value > UInt32.MaxValue)
1522 throw new OverflowException ();
1523 return new UIntConstant (target_type, (uint) Value, Location);
1524 case BuiltinTypeSpec.Type.Long:
1525 if (in_checked_context && Value > Int64.MaxValue)
1526 throw new OverflowException ();
1527 return new LongConstant (target_type, (long) Value, Location);
1528 case BuiltinTypeSpec.Type.Float:
1529 return new FloatConstant (target_type, (float) Value, Location);
1530 case BuiltinTypeSpec.Type.Double:
1531 return new DoubleConstant (target_type, (double) Value, Location);
1532 case BuiltinTypeSpec.Type.Char:
1533 if (in_checked_context && Value > Char.MaxValue)
1534 throw new OverflowException ();
1535 return new CharConstant (target_type, (char) Value, Location);
1536 case BuiltinTypeSpec.Type.Decimal:
1537 return new DecimalConstant (target_type, (decimal) Value, Location);
1545 public class FloatConstant : Constant {
1546 public readonly float Value;
1548 public FloatConstant (BuiltinTypes types, float v, Location loc)
1549 : this (types.Float, v, loc)
1553 public FloatConstant (TypeSpec type, float v, Location loc)
1557 eclass = ExprClass.Value;
1562 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1567 public override void Emit (EmitContext ec)
1569 ec.Emit (OpCodes.Ldc_R4, Value);
1572 public override object GetValue ()
1577 public override string GetValueAsLiteral ()
1579 return Value.ToString ();
1582 public override long GetValueAsLong ()
1584 throw new NotSupportedException ();
1587 public override bool IsDefaultValue {
1593 public override bool IsNegative {
1599 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1601 switch (target_type.BuiltinType) {
1602 case BuiltinTypeSpec.Type.Byte:
1603 if (in_checked_context) {
1604 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1605 throw new OverflowException ();
1607 return new ByteConstant (target_type, (byte) Value, Location);
1608 case BuiltinTypeSpec.Type.SByte:
1609 if (in_checked_context) {
1610 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1611 throw new OverflowException ();
1613 return new SByteConstant (target_type, (sbyte) Value, Location);
1614 case BuiltinTypeSpec.Type.Short:
1615 if (in_checked_context) {
1616 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1617 throw new OverflowException ();
1619 return new ShortConstant (target_type, (short) Value, Location);
1620 case BuiltinTypeSpec.Type.UShort:
1621 if (in_checked_context) {
1622 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1623 throw new OverflowException ();
1625 return new UShortConstant (target_type, (ushort) Value, Location);
1626 case BuiltinTypeSpec.Type.Int:
1627 if (in_checked_context) {
1628 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1629 throw new OverflowException ();
1631 return new IntConstant (target_type, (int) Value, Location);
1632 case BuiltinTypeSpec.Type.UInt:
1633 if (in_checked_context) {
1634 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1635 throw new OverflowException ();
1637 return new UIntConstant (target_type, (uint) Value, Location);
1638 case BuiltinTypeSpec.Type.Long:
1639 if (in_checked_context) {
1640 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1641 throw new OverflowException ();
1643 return new LongConstant (target_type, (long) Value, Location);
1644 case BuiltinTypeSpec.Type.ULong:
1645 if (in_checked_context) {
1646 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1647 throw new OverflowException ();
1649 return new ULongConstant (target_type, (ulong) Value, Location);
1650 case BuiltinTypeSpec.Type.Double:
1651 return new DoubleConstant (target_type, (double) Value, Location);
1652 case BuiltinTypeSpec.Type.Char:
1653 if (in_checked_context) {
1654 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1655 throw new OverflowException ();
1657 return new CharConstant (target_type, (char) Value, Location);
1658 case BuiltinTypeSpec.Type.Decimal:
1659 return new DecimalConstant (target_type, (decimal) Value, Location);
1667 public class DoubleConstant : Constant
1669 public readonly double Value;
1671 public DoubleConstant (BuiltinTypes types, double v, Location loc)
1672 : this (types.Double, v, loc)
1676 public DoubleConstant (TypeSpec type, double v, Location loc)
1680 eclass = ExprClass.Value;
1685 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1690 public override void Emit (EmitContext ec)
1692 ec.Emit (OpCodes.Ldc_R8, Value);
1695 public override object GetValue ()
1700 public override string GetValueAsLiteral ()
1702 return Value.ToString ();
1705 public override long GetValueAsLong ()
1707 throw new NotSupportedException ();
1710 public override bool IsDefaultValue {
1716 public override bool IsNegative {
1722 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1724 switch (target_type.BuiltinType) {
1725 case BuiltinTypeSpec.Type.Byte:
1726 if (in_checked_context) {
1727 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1728 throw new OverflowException ();
1730 return new ByteConstant (target_type, (byte) Value, Location);
1731 case BuiltinTypeSpec.Type.SByte:
1732 if (in_checked_context) {
1733 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1734 throw new OverflowException ();
1736 return new SByteConstant (target_type, (sbyte) Value, Location);
1737 case BuiltinTypeSpec.Type.Short:
1738 if (in_checked_context) {
1739 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1740 throw new OverflowException ();
1742 return new ShortConstant (target_type, (short) Value, Location);
1743 case BuiltinTypeSpec.Type.UShort:
1744 if (in_checked_context) {
1745 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1746 throw new OverflowException ();
1748 return new UShortConstant (target_type, (ushort) Value, Location);
1749 case BuiltinTypeSpec.Type.Int:
1750 if (in_checked_context) {
1751 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1752 throw new OverflowException ();
1754 return new IntConstant (target_type, (int) Value, Location);
1755 case BuiltinTypeSpec.Type.UInt:
1756 if (in_checked_context) {
1757 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1758 throw new OverflowException ();
1760 return new UIntConstant (target_type, (uint) Value, Location);
1761 case BuiltinTypeSpec.Type.Long:
1762 if (in_checked_context) {
1763 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1764 throw new OverflowException ();
1766 return new LongConstant (target_type, (long) Value, Location);
1767 case BuiltinTypeSpec.Type.ULong:
1768 if (in_checked_context) {
1769 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1770 throw new OverflowException ();
1772 return new ULongConstant (target_type, (ulong) Value, Location);
1773 case BuiltinTypeSpec.Type.Float:
1774 return new FloatConstant (target_type, (float) Value, Location);
1775 case BuiltinTypeSpec.Type.Char:
1776 if (in_checked_context) {
1777 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1778 throw new OverflowException ();
1780 return new CharConstant (target_type, (char) Value, Location);
1781 case BuiltinTypeSpec.Type.Decimal:
1782 return new DecimalConstant (target_type, (decimal) Value, Location);
1790 public class DecimalConstant : Constant {
1791 public readonly decimal Value;
1793 public DecimalConstant (BuiltinTypes types, decimal d, Location loc)
1794 : this (types.Decimal, d, loc)
1798 public DecimalConstant (TypeSpec type, decimal d, Location loc)
1802 eclass = ExprClass.Value;
1807 public override void Emit (EmitContext ec)
1811 int [] words = decimal.GetBits (Value);
1812 int power = (words [3] >> 16) & 0xff;
1815 if (Value <= int.MaxValue && Value >= int.MinValue) {
1816 m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc);
1821 ec.EmitInt ((int) Value);
1822 ec.Emit (OpCodes.Newobj, m);
1826 if (Value <= long.MaxValue && Value >= long.MinValue) {
1827 m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc);
1832 ec.EmitLong ((long) Value);
1833 ec.Emit (OpCodes.Newobj, m);
1838 ec.EmitInt (words [0]);
1839 ec.EmitInt (words [1]);
1840 ec.EmitInt (words [2]);
1843 ec.EmitInt (words [3] >> 31);
1848 m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc);
1850 ec.Emit (OpCodes.Newobj, m);
1854 public override bool IsDefaultValue {
1860 public override bool IsNegative {
1866 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1868 switch (target_type.BuiltinType) {
1869 case BuiltinTypeSpec.Type.SByte:
1870 return new SByteConstant (target_type, (sbyte) Value, loc);
1871 case BuiltinTypeSpec.Type.Byte:
1872 return new ByteConstant (target_type, (byte) Value, loc);
1873 case BuiltinTypeSpec.Type.Short:
1874 return new ShortConstant (target_type, (short) Value, loc);
1875 case BuiltinTypeSpec.Type.UShort:
1876 return new UShortConstant (target_type, (ushort) Value, loc);
1877 case BuiltinTypeSpec.Type.Int:
1878 return new IntConstant (target_type, (int) Value, loc);
1879 case BuiltinTypeSpec.Type.UInt:
1880 return new UIntConstant (target_type, (uint) Value, loc);
1881 case BuiltinTypeSpec.Type.Long:
1882 return new LongConstant (target_type, (long) Value, loc);
1883 case BuiltinTypeSpec.Type.ULong:
1884 return new ULongConstant (target_type, (ulong) Value, loc);
1885 case BuiltinTypeSpec.Type.Char:
1886 return new CharConstant (target_type, (char) Value, loc);
1887 case BuiltinTypeSpec.Type.Float:
1888 return new FloatConstant (target_type, (float) Value, loc);
1889 case BuiltinTypeSpec.Type.Double:
1890 return new DoubleConstant (target_type, (double) Value, loc);
1896 public override object GetValue ()
1901 public override string GetValueAsLiteral ()
1903 return Value.ToString () + "M";
1906 public override long GetValueAsLong ()
1908 throw new NotSupportedException ();
1912 public class StringConstant : Constant {
1913 public readonly string Value;
1915 public StringConstant (BuiltinTypes types, string s, Location loc)
1916 : this (types.String, s, loc)
1920 public StringConstant (TypeSpec type, string s, Location loc)
1924 eclass = ExprClass.Value;
1929 public override object GetValue ()
1934 public override string GetValueAsLiteral ()
1936 // FIXME: Escape the string.
1937 return "\"" + Value + "\"";
1940 public override long GetValueAsLong ()
1942 throw new NotSupportedException ();
1945 public override void Emit (EmitContext ec)
1947 if (Value == null) {
1948 ec.Emit (OpCodes.Ldnull);
1953 // Use string.Empty for both literals and constants even if
1954 // it's not allowed at language level
1956 if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) {
1957 var string_type = ec.BuiltinTypes.String;
1958 if (ec.CurrentType != string_type) {
1959 var m = ec.Module.PredefinedMembers.StringEmpty.Get ();
1961 ec.Emit (OpCodes.Ldsfld, m);
1967 ec.Emit (OpCodes.Ldstr, Value);
1970 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1973 if (type != targetType)
1979 public override bool IsDefaultValue {
1981 return Value == null;
1985 public override bool IsNegative {
1991 public override bool IsNull {
1993 return IsDefaultValue;
1997 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2004 // Null constant can have its own type, think of `default (Foo)'
2006 public class NullConstant : Constant
2008 public NullConstant (TypeSpec type, Location loc)
2011 eclass = ExprClass.Value;
2015 public override Expression CreateExpressionTree (ResolveContext ec)
2017 if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2018 // Optimized version, also avoids referencing literal internal type
2019 Arguments args = new Arguments (1);
2020 args.Add (new Argument (this));
2021 return CreateExpressionFactoryCall (ec, "Constant", args);
2024 return base.CreateExpressionTree (ec);
2027 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
2029 switch (targetType.BuiltinType) {
2030 case BuiltinTypeSpec.Type.Object:
2031 // Type it as string cast
2032 enc.Encode (rc.Module.Compiler.BuiltinTypes.String);
2033 goto case BuiltinTypeSpec.Type.String;
2034 case BuiltinTypeSpec.Type.String:
2035 case BuiltinTypeSpec.Type.Type:
2036 enc.Encode (byte.MaxValue);
2039 var ac = targetType as ArrayContainer;
2040 if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) {
2041 enc.Encode (uint.MaxValue);
2048 base.EncodeAttributeValue (rc, enc, targetType);
2051 public override void Emit (EmitContext ec)
2053 ec.Emit (OpCodes.Ldnull);
2055 // Only to make verifier happy
2056 if (type.IsGenericParameter)
2057 ec.Emit (OpCodes.Unbox_Any, type);
2060 public override string ExprClassName {
2062 return GetSignatureForError ();
2066 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2068 if (targetType.IsPointer) {
2069 if (IsLiteral || this is NullPointer)
2070 return new NullPointer (targetType, loc);
2075 // Exlude internal compiler types
2076 if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic)
2079 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2082 if (TypeSpec.IsReferenceType (targetType))
2083 return new NullConstant (targetType, loc);
2085 if (targetType.IsNullableType)
2086 return Nullable.LiftedNull.Create (targetType, loc);
2091 public override Constant ConvertImplicitly (TypeSpec targetType)
2093 return ConvertExplicitly (false, targetType);
2096 public override string GetSignatureForError ()
2101 public override object GetValue ()
2106 public override string GetValueAsLiteral ()
2108 return GetSignatureForError ();
2111 public override long GetValueAsLong ()
2113 throw new NotSupportedException ();
2116 public override bool IsDefaultValue {
2117 get { return true; }
2120 public override bool IsNegative {
2121 get { return false; }
2124 public override bool IsNull {
2125 get { return true; }
2128 public override bool IsZeroInteger {
2129 get { return true; }
2135 // A null constant in a pointer context
2137 class NullPointer : NullConstant
2139 public NullPointer (TypeSpec type, Location loc)
2144 public override Expression CreateExpressionTree (ResolveContext ec)
2146 Error_PointerInsideExpressionTree (ec);
2147 return base.CreateExpressionTree (ec);
2150 public override void Emit (EmitContext ec)
2153 // Emits null pointer
2155 ec.Emit (OpCodes.Ldc_I4_0);
2156 ec.Emit (OpCodes.Conv_U);
2161 /// The value is constant, but when emitted has a side effect. This is
2162 /// used by BitwiseAnd to ensure that the second expression is invoked
2163 /// regardless of the value of the left side.
2165 public class SideEffectConstant : Constant
2167 public readonly Constant value;
2168 Expression side_effect;
2170 public SideEffectConstant (Constant value, Expression side_effect, Location loc)
2175 eclass = ExprClass.Value;
2177 while (side_effect is SideEffectConstant)
2178 side_effect = ((SideEffectConstant) side_effect).side_effect;
2179 this.side_effect = side_effect;
2182 public override bool IsSideEffectFree {
2188 public override object GetValue ()
2190 return value.GetValue ();
2193 public override string GetValueAsLiteral ()
2195 return value.GetValueAsLiteral ();
2198 public override long GetValueAsLong ()
2200 return value.GetValueAsLong ();
2203 public override void Emit (EmitContext ec)
2205 side_effect.EmitSideEffect (ec);
2209 public override void EmitSideEffect (EmitContext ec)
2211 side_effect.EmitSideEffect (ec);
2212 value.EmitSideEffect (ec);
2215 public override bool IsDefaultValue {
2216 get { return value.IsDefaultValue; }
2219 public override bool IsNegative {
2220 get { return value.IsNegative; }
2223 public override bool IsZeroInteger {
2224 get { return value.IsZeroInteger; }
2227 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2229 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2230 if (new_value == null)
2233 var c = new SideEffectConstant (new_value, side_effect, new_value.Location);
2234 c.type = target_type;