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.
10 // Copyright 2011 Xamarin Inc
14 using System.Globalization;
17 using IKVM.Reflection.Emit;
19 using System.Reflection.Emit;
22 namespace Mono.CSharp {
25 /// Base class for constants and literals.
27 public abstract class Constant : Expression
29 static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
31 protected Constant (Location loc)
36 override public string ToString ()
38 return this.GetType ().Name + " (" + GetValueAsLiteral () + ")";
42 /// This is used to obtain the actual value of the literal
43 /// cast into an object.
45 public abstract object GetValue ();
47 public abstract long GetValueAsLong ();
49 public abstract string GetValueAsLiteral ();
53 // Returns an object value which is typed to contant type
55 public virtual object GetTypedValue ()
61 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
63 if (!expl && IsLiteral &&
64 BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
65 BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) {
66 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
67 GetValueAsLiteral (), target.GetSignatureForError ());
69 base.Error_ValueCannotBeConverted (ec, target, expl);
73 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
75 Constant c = ConvertImplicitly (type);
77 Error_ValueCannotBeConverted (ec, type, false);
82 public override bool ContainsEmitWithAwait ()
87 public virtual Constant ConvertImplicitly (TypeSpec type)
89 if (this.type == type)
92 if (Convert.ImplicitNumericConversion (this, type) == null)
96 object constant_value = ChangeType (GetValue (), type, out fail);
99 // We should always catch the error before this is ever
100 // reached, by calling Convert.ImplicitStandardConversionExists
102 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
103 Type.GetSignatureForError (), type.GetSignatureForError ());
106 return CreateConstantFromValue (type, constant_value, loc);
110 // Returns a constant instance based on Type
112 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
114 switch (t.BuiltinType) {
115 case BuiltinTypeSpec.Type.Int:
116 return new IntConstant (t, (int) v, loc);
117 case BuiltinTypeSpec.Type.String:
118 return new StringConstant (t, (string) v, loc);
119 case BuiltinTypeSpec.Type.UInt:
120 return new UIntConstant (t, (uint) v, loc);
121 case BuiltinTypeSpec.Type.Long:
122 return new LongConstant (t, (long) v, loc);
123 case BuiltinTypeSpec.Type.ULong:
124 return new ULongConstant (t, (ulong) v, loc);
125 case BuiltinTypeSpec.Type.Float:
126 return new FloatConstant (t, (float) v, loc);
127 case BuiltinTypeSpec.Type.Double:
128 return new DoubleConstant (t, (double) v, loc);
129 case BuiltinTypeSpec.Type.Short:
130 return new ShortConstant (t, (short) v, loc);
131 case BuiltinTypeSpec.Type.UShort:
132 return new UShortConstant (t, (ushort) v, loc);
133 case BuiltinTypeSpec.Type.SByte:
134 return new SByteConstant (t, (sbyte) v, loc);
135 case BuiltinTypeSpec.Type.Byte:
136 return new ByteConstant (t, (byte) v, loc);
137 case BuiltinTypeSpec.Type.Char:
138 return new CharConstant (t, (char) v, loc);
139 case BuiltinTypeSpec.Type.Bool:
140 return new BoolConstant (t, (bool) v, loc);
141 case BuiltinTypeSpec.Type.Decimal:
142 return new DecimalConstant (t, (decimal) v, loc);
146 var real_type = EnumSpec.GetUnderlyingType (t);
147 return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t);
151 if (t.IsNullableType)
152 return Nullable.LiftedNull.Create (t, loc);
154 if (TypeSpec.IsReferenceType (t))
155 return new NullConstant (t, loc);
159 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ());
165 public override Expression CreateExpressionTree (ResolveContext ec)
167 Arguments args = new Arguments (2);
168 args.Add (new Argument (this));
169 args.Add (new Argument (new TypeOf (type, loc)));
171 return CreateExpressionFactoryCall (ec, "Constant", args);
175 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
176 /// It throws OverflowException
178 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
179 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
181 // This is a custom version of Convert.ChangeType() which works
182 // with the TypeBuilder defined types when compiling corlib.
183 static object ChangeType (object value, TypeSpec targetType, out bool error)
185 IConvertible convert_value = value as IConvertible;
187 if (convert_value == null) {
193 // We cannot rely on build-in type conversions as they are
194 // more limited than what C# supports.
195 // See char -> float/decimal/double conversion
199 switch (targetType.BuiltinType) {
200 case BuiltinTypeSpec.Type.Bool:
201 return convert_value.ToBoolean (nfi);
202 case BuiltinTypeSpec.Type.Byte:
203 return convert_value.ToByte (nfi);
204 case BuiltinTypeSpec.Type.Char:
205 return convert_value.ToChar (nfi);
206 case BuiltinTypeSpec.Type.Short:
207 return convert_value.ToInt16 (nfi);
208 case BuiltinTypeSpec.Type.Int:
209 return convert_value.ToInt32 (nfi);
210 case BuiltinTypeSpec.Type.Long:
211 return convert_value.ToInt64 (nfi);
212 case BuiltinTypeSpec.Type.SByte:
213 return convert_value.ToSByte (nfi);
214 case BuiltinTypeSpec.Type.Decimal:
215 if (convert_value.GetType () == typeof (char))
216 return (decimal) convert_value.ToInt32 (nfi);
217 return convert_value.ToDecimal (nfi);
218 case BuiltinTypeSpec.Type.Double:
219 if (convert_value.GetType () == typeof (char))
220 return (double) convert_value.ToInt32 (nfi);
221 return convert_value.ToDouble (nfi);
222 case BuiltinTypeSpec.Type.Float:
223 if (convert_value.GetType () == typeof (char))
224 return (float) convert_value.ToInt32 (nfi);
225 return convert_value.ToSingle (nfi);
226 case BuiltinTypeSpec.Type.String:
227 return convert_value.ToString (nfi);
228 case BuiltinTypeSpec.Type.UShort:
229 return convert_value.ToUInt16 (nfi);
230 case BuiltinTypeSpec.Type.UInt:
231 return convert_value.ToUInt32 (nfi);
232 case BuiltinTypeSpec.Type.ULong:
233 return convert_value.ToUInt64 (nfi);
234 case BuiltinTypeSpec.Type.Object:
244 protected override Expression DoResolve (ResolveContext rc)
250 // Attempts to do a compile-time folding of a constant cast and handles
251 // error reporting for constant overlows only, on normal conversion
252 // errors returns null
254 public Constant Reduce (ResolveContext ec, TypeSpec target_type)
257 return TryReduceConstant (ec, target_type);
258 } catch (OverflowException) {
259 if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
260 ec.Report.Error (221, loc,
261 "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
262 GetValueAsLiteral (), target_type.GetSignatureForError ());
264 Error_ValueCannotBeConverted (ec, target_type, false);
267 return New.Constantify (target_type, loc);
271 public Constant TryReduce (ResolveContext rc, TypeSpec targetType)
274 return TryReduceConstant (rc, targetType);
275 } catch (OverflowException) {
280 Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type)
282 if (Type == target_type) {
284 // Reducing literal value produces a new constant. Syntactically 10 is not same as (int)10
287 return CreateConstantFromValue (target_type, GetValue (), loc);
293 if (target_type.IsEnum) {
294 c = TryReduceConstant (ec, EnumSpec.GetUnderlyingType (target_type));
298 return new EnumConstant (c, target_type);
301 return ConvertExplicitly (ec.ConstantCheckState, target_type);
305 /// Need to pass type as the constant can require a boxing
306 /// and in such case no optimization is possible
308 public bool IsDefaultInitializer (TypeSpec type)
311 return IsDefaultValue;
313 return this is NullLiteral;
316 public abstract bool IsDefaultValue {
320 public abstract bool IsNegative {
325 // When constant is declared as literal
327 public virtual bool IsLiteral {
328 get { return false; }
331 public virtual bool IsOneInteger {
332 get { return false; }
335 public override bool IsSideEffectFree {
342 // Returns true iff 1) the stack type of this is one of Object,
343 // int32, int64 and 2) this == 0 or this == null.
345 public virtual bool IsZeroInteger {
346 get { return false; }
349 public override void EmitSideEffect (EmitContext ec)
354 public sealed override Expression Clone (CloneContext clonectx)
356 // No cloning is not needed for constants
360 protected override void CloneTo (CloneContext clonectx, Expression target)
362 throw new NotSupportedException ("should not be reached");
365 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
368 return base.MakeExpression (ctx);
370 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
374 public new bool Resolve (ResolveContext rc)
376 // It exists only as hint not to call Resolve on constants
381 public abstract class IntegralConstant : Constant
383 protected IntegralConstant (TypeSpec type, Location loc)
387 eclass = ExprClass.Value;
390 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
393 ConvertExplicitly (true, target);
394 base.Error_ValueCannotBeConverted (ec, target, expl);
398 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
399 GetValue ().ToString (), target.GetSignatureForError ());
403 public override string GetValueAsLiteral ()
405 return GetValue ().ToString ();
408 public abstract Constant Increment ();
411 public class BoolConstant : Constant {
412 public readonly bool Value;
414 public BoolConstant (BuiltinTypes types, bool val, Location loc)
415 : this (types.Bool, val, loc)
419 public BoolConstant (TypeSpec type, bool val, Location loc)
422 eclass = ExprClass.Value;
428 public override object GetValue ()
430 return (object) Value;
433 public override string GetValueAsLiteral ()
435 return Value ? "true" : "false";
438 public override long GetValueAsLong ()
440 return Value ? 1 : 0;
443 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
448 public override void Emit (EmitContext ec)
456 public override bool IsDefaultValue {
462 public override bool IsNegative {
468 public override bool IsZeroInteger {
469 get { return Value == false; }
472 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
479 public class ByteConstant : IntegralConstant
481 public readonly byte Value;
483 public ByteConstant (BuiltinTypes types, byte v, Location loc)
484 : this (types.Byte, v, loc)
488 public ByteConstant (TypeSpec type, byte v, Location loc)
494 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
499 public override void Emit (EmitContext ec)
504 public override object GetValue ()
509 public override long GetValueAsLong ()
514 public override Constant Increment ()
516 return new ByteConstant (type, checked ((byte)(Value + 1)), loc);
519 public override bool IsDefaultValue {
525 public override bool IsOneInteger {
531 public override bool IsNegative {
537 public override bool IsZeroInteger {
538 get { return Value == 0; }
541 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
543 switch (target_type.BuiltinType) {
544 case BuiltinTypeSpec.Type.SByte:
545 if (in_checked_context){
546 if (Value > SByte.MaxValue)
547 throw new OverflowException ();
549 return new SByteConstant (target_type, (sbyte) Value, Location);
550 case BuiltinTypeSpec.Type.Short:
551 return new ShortConstant (target_type, (short) Value, Location);
552 case BuiltinTypeSpec.Type.UShort:
553 return new UShortConstant (target_type, (ushort) Value, Location);
554 case BuiltinTypeSpec.Type.Int:
555 return new IntConstant (target_type, (int) Value, Location);
556 case BuiltinTypeSpec.Type.UInt:
557 return new UIntConstant (target_type, (uint) Value, Location);
558 case BuiltinTypeSpec.Type.Long:
559 return new LongConstant (target_type, (long) Value, Location);
560 case BuiltinTypeSpec.Type.ULong:
561 return new ULongConstant (target_type, (ulong) Value, Location);
562 case BuiltinTypeSpec.Type.Float:
563 return new FloatConstant (target_type, (float) Value, Location);
564 case BuiltinTypeSpec.Type.Double:
565 return new DoubleConstant (target_type, (double) Value, Location);
566 case BuiltinTypeSpec.Type.Char:
567 return new CharConstant (target_type, (char) Value, Location);
568 case BuiltinTypeSpec.Type.Decimal:
569 return new DecimalConstant (target_type, (decimal) Value, Location);
577 public class CharConstant : Constant {
578 public readonly char Value;
580 public CharConstant (BuiltinTypes types, char v, Location loc)
581 : this (types.Char, v, loc)
585 public CharConstant (TypeSpec type, char v, Location loc)
589 eclass = ExprClass.Value;
594 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
596 enc.Encode ((ushort) Value);
599 public override void Emit (EmitContext ec)
604 static string descape (char c)
630 return c.ToString ();
633 public override object GetValue ()
638 public override long GetValueAsLong ()
643 public override string GetValueAsLiteral ()
645 return "\"" + descape (Value) + "\"";
648 public override bool IsDefaultValue {
654 public override bool IsNegative {
660 public override bool IsZeroInteger {
661 get { return Value == '\0'; }
664 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
666 switch (target_type.BuiltinType) {
667 case BuiltinTypeSpec.Type.Byte:
668 if (in_checked_context) {
669 if (Value < Byte.MinValue || Value > Byte.MaxValue)
670 throw new OverflowException ();
672 return new ByteConstant (target_type, (byte) Value, Location);
673 case BuiltinTypeSpec.Type.SByte:
674 if (in_checked_context) {
675 if (Value > SByte.MaxValue)
676 throw new OverflowException ();
678 return new SByteConstant (target_type, (sbyte) Value, Location);
680 case BuiltinTypeSpec.Type.Short:
681 if (in_checked_context) {
682 if (Value > Int16.MaxValue)
683 throw new OverflowException ();
685 return new ShortConstant (target_type, (short) Value, Location);
686 case BuiltinTypeSpec.Type.Int:
687 return new IntConstant (target_type, (int) Value, Location);
688 case BuiltinTypeSpec.Type.UInt:
689 return new UIntConstant (target_type, (uint) Value, Location);
690 case BuiltinTypeSpec.Type.Long:
691 return new LongConstant (target_type, (long) Value, Location);
692 case BuiltinTypeSpec.Type.ULong:
693 return new ULongConstant (target_type, (ulong) Value, Location);
694 case BuiltinTypeSpec.Type.Float:
695 return new FloatConstant (target_type, (float) Value, Location);
696 case BuiltinTypeSpec.Type.Double:
697 return new DoubleConstant (target_type, (double) Value, Location);
698 case BuiltinTypeSpec.Type.Decimal:
699 return new DecimalConstant (target_type, (decimal) Value, Location);
707 public class SByteConstant : IntegralConstant
709 public readonly sbyte Value;
711 public SByteConstant (BuiltinTypes types, sbyte v, Location loc)
712 : this (types.SByte, v, loc)
716 public SByteConstant (TypeSpec type, sbyte v, Location loc)
722 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
727 public override void Emit (EmitContext ec)
732 public override object GetValue ()
737 public override long GetValueAsLong ()
742 public override Constant Increment ()
744 return new SByteConstant (type, checked((sbyte)(Value + 1)), loc);
747 public override bool IsDefaultValue {
753 public override bool IsNegative {
759 public override bool IsOneInteger {
765 public override bool IsZeroInteger {
766 get { return Value == 0; }
769 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
771 switch (target_type.BuiltinType) {
772 case BuiltinTypeSpec.Type.Byte:
773 if (in_checked_context && Value < 0)
774 throw new OverflowException ();
775 return new ByteConstant (target_type, (byte) Value, Location);
776 case BuiltinTypeSpec.Type.Short:
777 return new ShortConstant (target_type, (short) Value, Location);
778 case BuiltinTypeSpec.Type.UShort:
779 if (in_checked_context && Value < 0)
780 throw new OverflowException ();
781 return new UShortConstant (target_type, (ushort) Value, Location);
782 case BuiltinTypeSpec.Type.Int:
783 return new IntConstant (target_type, (int) Value, Location);
784 case BuiltinTypeSpec.Type.UInt:
785 if (in_checked_context && Value < 0)
786 throw new OverflowException ();
787 return new UIntConstant (target_type, (uint) Value, Location);
788 case BuiltinTypeSpec.Type.Long:
789 return new LongConstant (target_type, (long) Value, Location);
790 case BuiltinTypeSpec.Type.ULong:
791 if (in_checked_context && Value < 0)
792 throw new OverflowException ();
793 return new ULongConstant (target_type, (ulong) Value, Location);
794 case BuiltinTypeSpec.Type.Float:
795 return new FloatConstant (target_type, (float) Value, Location);
796 case BuiltinTypeSpec.Type.Double:
797 return new DoubleConstant (target_type, (double) Value, Location);
798 case BuiltinTypeSpec.Type.Char:
799 if (in_checked_context && Value < 0)
800 throw new OverflowException ();
801 return new CharConstant (target_type, (char) Value, Location);
802 case BuiltinTypeSpec.Type.Decimal:
803 return new DecimalConstant (target_type, (decimal) Value, Location);
811 public class ShortConstant : IntegralConstant {
812 public readonly short Value;
814 public ShortConstant (BuiltinTypes types, short v, Location loc)
815 : this (types.Short, v, loc)
819 public ShortConstant (TypeSpec type, short v, Location loc)
825 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
830 public override void Emit (EmitContext ec)
835 public override object GetValue ()
840 public override long GetValueAsLong ()
845 public override Constant Increment ()
847 return new ShortConstant (type, checked((short)(Value + 1)), loc);
850 public override bool IsDefaultValue {
856 public override bool IsZeroInteger {
857 get { return Value == 0; }
860 public override bool IsNegative {
866 public override bool IsOneInteger {
872 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
874 switch (target_type.BuiltinType) {
875 case BuiltinTypeSpec.Type.Byte:
876 if (in_checked_context) {
877 if (Value < Byte.MinValue || Value > Byte.MaxValue)
878 throw new OverflowException ();
880 return new ByteConstant (target_type, (byte) Value, Location);
881 case BuiltinTypeSpec.Type.SByte:
882 if (in_checked_context) {
883 if (Value < SByte.MinValue || Value > SByte.MaxValue)
884 throw new OverflowException ();
886 return new SByteConstant (target_type, (sbyte) Value, Location);
887 case BuiltinTypeSpec.Type.UShort:
888 if (in_checked_context && Value < 0)
889 throw new OverflowException ();
891 return new UShortConstant (target_type, (ushort) Value, Location);
892 case BuiltinTypeSpec.Type.Int:
893 return new IntConstant (target_type, (int) Value, Location);
894 case BuiltinTypeSpec.Type.UInt:
895 if (in_checked_context && Value < 0)
896 throw new OverflowException ();
897 return new UIntConstant (target_type, (uint) Value, Location);
898 case BuiltinTypeSpec.Type.Long:
899 return new LongConstant (target_type, (long) Value, Location);
900 case BuiltinTypeSpec.Type.ULong:
901 if (in_checked_context && Value < 0)
902 throw new OverflowException ();
903 return new ULongConstant (target_type, (ulong) Value, Location);
904 case BuiltinTypeSpec.Type.Float:
905 return new FloatConstant (target_type, (float) Value, Location);
906 case BuiltinTypeSpec.Type.Double:
907 return new DoubleConstant (target_type, (double) Value, Location);
908 case BuiltinTypeSpec.Type.Char:
909 if (in_checked_context) {
910 if (Value < Char.MinValue)
911 throw new OverflowException ();
913 return new CharConstant (target_type, (char) Value, Location);
914 case BuiltinTypeSpec.Type.Decimal:
915 return new DecimalConstant (target_type, (decimal) Value, Location);
923 public class UShortConstant : IntegralConstant
925 public readonly ushort Value;
927 public UShortConstant (BuiltinTypes types, ushort v, Location loc)
928 : this (types.UShort, v, loc)
932 public UShortConstant (TypeSpec type, ushort v, Location loc)
938 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
943 public override void Emit (EmitContext ec)
948 public override object GetValue ()
953 public override long GetValueAsLong ()
958 public override Constant Increment ()
960 return new UShortConstant (type, checked((ushort)(Value + 1)), loc);
963 public override bool IsDefaultValue {
969 public override bool IsNegative {
975 public override bool IsOneInteger {
981 public override bool IsZeroInteger {
982 get { return Value == 0; }
985 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
987 switch (target_type.BuiltinType) {
988 case BuiltinTypeSpec.Type.Byte:
989 if (in_checked_context) {
990 if (Value > Byte.MaxValue)
991 throw new OverflowException ();
993 return new ByteConstant (target_type, (byte) Value, Location);
994 case BuiltinTypeSpec.Type.SByte:
995 if (in_checked_context) {
996 if (Value > SByte.MaxValue)
997 throw new OverflowException ();
999 return new SByteConstant (target_type, (sbyte) Value, Location);
1000 case BuiltinTypeSpec.Type.Short:
1001 if (in_checked_context) {
1002 if (Value > Int16.MaxValue)
1003 throw new OverflowException ();
1005 return new ShortConstant (target_type, (short) Value, Location);
1006 case BuiltinTypeSpec.Type.Int:
1007 return new IntConstant (target_type, (int) Value, Location);
1008 case BuiltinTypeSpec.Type.UInt:
1009 return new UIntConstant (target_type, (uint) Value, Location);
1010 case BuiltinTypeSpec.Type.Long:
1011 return new LongConstant (target_type, (long) Value, Location);
1012 case BuiltinTypeSpec.Type.ULong:
1013 return new ULongConstant (target_type, (ulong) Value, Location);
1014 case BuiltinTypeSpec.Type.Float:
1015 return new FloatConstant (target_type, (float) Value, Location);
1016 case BuiltinTypeSpec.Type.Double:
1017 return new DoubleConstant (target_type, (double) Value, Location);
1018 case BuiltinTypeSpec.Type.Char:
1019 if (in_checked_context) {
1020 if (Value > Char.MaxValue)
1021 throw new OverflowException ();
1023 return new CharConstant (target_type, (char) Value, Location);
1024 case BuiltinTypeSpec.Type.Decimal:
1025 return new DecimalConstant (target_type, (decimal) Value, Location);
1032 public class IntConstant : IntegralConstant
1034 public readonly int Value;
1036 public IntConstant (BuiltinTypes types, int v, Location loc)
1037 : this (types.Int, v, loc)
1041 public IntConstant (TypeSpec type, int v, Location loc)
1047 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1052 public override void Emit (EmitContext ec)
1057 public override object GetValue ()
1062 public override long GetValueAsLong ()
1067 public override Constant Increment ()
1069 return new IntConstant (type, checked(Value + 1), loc);
1072 public override bool IsDefaultValue {
1078 public override bool IsNegative {
1084 public override bool IsOneInteger {
1090 public override bool IsZeroInteger {
1091 get { return Value == 0; }
1094 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1096 switch (target_type.BuiltinType) {
1097 case BuiltinTypeSpec.Type.Byte:
1098 if (in_checked_context) {
1099 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1100 throw new OverflowException ();
1102 return new ByteConstant (target_type, (byte) Value, Location);
1103 case BuiltinTypeSpec.Type.SByte:
1104 if (in_checked_context) {
1105 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1106 throw new OverflowException ();
1108 return new SByteConstant (target_type, (sbyte) Value, Location);
1109 case BuiltinTypeSpec.Type.Short:
1110 if (in_checked_context) {
1111 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1112 throw new OverflowException ();
1114 return new ShortConstant (target_type, (short) Value, Location);
1115 case BuiltinTypeSpec.Type.UShort:
1116 if (in_checked_context) {
1117 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1118 throw new OverflowException ();
1120 return new UShortConstant (target_type, (ushort) Value, Location);
1121 case BuiltinTypeSpec.Type.UInt:
1122 if (in_checked_context) {
1123 if (Value < UInt32.MinValue)
1124 throw new OverflowException ();
1126 return new UIntConstant (target_type, (uint) Value, Location);
1127 case BuiltinTypeSpec.Type.Long:
1128 return new LongConstant (target_type, (long) Value, Location);
1129 case BuiltinTypeSpec.Type.ULong:
1130 if (in_checked_context && Value < 0)
1131 throw new OverflowException ();
1132 return new ULongConstant (target_type, (ulong) Value, Location);
1133 case BuiltinTypeSpec.Type.Float:
1134 return new FloatConstant (target_type, (float) Value, Location);
1135 case BuiltinTypeSpec.Type.Double:
1136 return new DoubleConstant (target_type, (double) Value, Location);
1137 case BuiltinTypeSpec.Type.Char:
1138 if (in_checked_context) {
1139 if (Value < Char.MinValue || Value > Char.MaxValue)
1140 throw new OverflowException ();
1142 return new CharConstant (target_type, (char) Value, Location);
1143 case BuiltinTypeSpec.Type.Decimal:
1144 return new DecimalConstant (target_type, (decimal) Value, Location);
1150 public override Constant ConvertImplicitly (TypeSpec type)
1152 if (this.type == type)
1155 Constant c = TryImplicitIntConversion (type);
1157 return c; //.Resolve (rc);
1159 return base.ConvertImplicitly (type);
1163 /// Attempts to perform an implicit constant conversion of the IntConstant
1164 /// into a different data type using casts (See Implicit Constant
1165 /// Expression Conversions)
1167 Constant TryImplicitIntConversion (TypeSpec target_type)
1169 switch (target_type.BuiltinType) {
1170 case BuiltinTypeSpec.Type.SByte:
1171 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1172 return new SByteConstant (target_type, (sbyte) Value, loc);
1174 case BuiltinTypeSpec.Type.Byte:
1175 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1176 return new ByteConstant (target_type, (byte) Value, loc);
1178 case BuiltinTypeSpec.Type.Short:
1179 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1180 return new ShortConstant (target_type, (short) Value, loc);
1182 case BuiltinTypeSpec.Type.UShort:
1183 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1184 return new UShortConstant (target_type, (ushort) Value, loc);
1186 case BuiltinTypeSpec.Type.UInt:
1188 return new UIntConstant (target_type, (uint) Value, loc);
1190 case BuiltinTypeSpec.Type.ULong:
1192 // we can optimize this case: a positive int32
1193 // always fits on a uint64. But we need an opcode
1197 return new ULongConstant (target_type, (ulong) Value, loc);
1199 case BuiltinTypeSpec.Type.Double:
1200 return new DoubleConstant (target_type, (double) Value, loc);
1201 case BuiltinTypeSpec.Type.Float:
1202 return new FloatConstant (target_type, (float) Value, loc);
1209 public class UIntConstant : IntegralConstant {
1210 public readonly uint Value;
1212 public UIntConstant (BuiltinTypes types, uint v, Location loc)
1213 : this (types.UInt, v, loc)
1217 public UIntConstant (TypeSpec type, uint v, Location loc)
1223 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1228 public override void Emit (EmitContext ec)
1230 ec.EmitInt (unchecked ((int) Value));
1233 public override object GetValue ()
1238 public override long GetValueAsLong ()
1243 public override Constant Increment ()
1245 return new UIntConstant (type, checked(Value + 1), loc);
1248 public override bool IsDefaultValue {
1254 public override bool IsNegative {
1260 public override bool IsOneInteger {
1266 public override bool IsZeroInteger {
1267 get { return Value == 0; }
1270 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1272 switch (target_type.BuiltinType) {
1273 case BuiltinTypeSpec.Type.Byte:
1274 if (in_checked_context) {
1275 if (Value < 0 || Value > byte.MaxValue)
1276 throw new OverflowException ();
1278 return new ByteConstant (target_type, (byte) Value, Location);
1279 case BuiltinTypeSpec.Type.SByte:
1280 if (in_checked_context) {
1281 if (Value > SByte.MaxValue)
1282 throw new OverflowException ();
1284 return new SByteConstant (target_type, (sbyte) Value, Location);
1285 case BuiltinTypeSpec.Type.Short:
1286 if (in_checked_context) {
1287 if (Value > Int16.MaxValue)
1288 throw new OverflowException ();
1290 return new ShortConstant (target_type, (short) Value, Location);
1291 case BuiltinTypeSpec.Type.UShort:
1292 if (in_checked_context) {
1293 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1294 throw new OverflowException ();
1296 return new UShortConstant (target_type, (ushort) Value, Location);
1297 case BuiltinTypeSpec.Type.Int:
1298 if (in_checked_context) {
1299 if (Value > Int32.MaxValue)
1300 throw new OverflowException ();
1302 return new IntConstant (target_type, (int) Value, Location);
1303 case BuiltinTypeSpec.Type.Long:
1304 return new LongConstant (target_type, (long) Value, Location);
1305 case BuiltinTypeSpec.Type.ULong:
1306 return new ULongConstant (target_type, (ulong) Value, Location);
1307 case BuiltinTypeSpec.Type.Float:
1308 return new FloatConstant (target_type, (float) Value, Location);
1309 case BuiltinTypeSpec.Type.Double:
1310 return new DoubleConstant (target_type, (double) Value, Location);
1311 case BuiltinTypeSpec.Type.Char:
1312 if (in_checked_context) {
1313 if (Value < Char.MinValue || Value > Char.MaxValue)
1314 throw new OverflowException ();
1316 return new CharConstant (target_type, (char) Value, Location);
1317 case BuiltinTypeSpec.Type.Decimal:
1318 return new DecimalConstant (target_type, (decimal) Value, Location);
1326 public class LongConstant : IntegralConstant {
1327 public readonly long Value;
1329 public LongConstant (BuiltinTypes types, long v, Location loc)
1330 : this (types.Long, v, loc)
1334 public LongConstant (TypeSpec type, long v, Location loc)
1340 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1345 public override void Emit (EmitContext ec)
1347 ec.EmitLong (Value);
1350 public override object GetValue ()
1355 public override long GetValueAsLong ()
1360 public override Constant Increment ()
1362 return new LongConstant (type, checked(Value + 1), loc);
1365 public override bool IsDefaultValue {
1371 public override bool IsNegative {
1377 public override bool IsOneInteger {
1383 public override bool IsZeroInteger {
1384 get { return Value == 0; }
1387 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1389 switch (target_type.BuiltinType) {
1390 case BuiltinTypeSpec.Type.Byte:
1391 if (in_checked_context) {
1392 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1393 throw new OverflowException ();
1395 return new ByteConstant (target_type, (byte) Value, Location);
1396 case BuiltinTypeSpec.Type.SByte:
1397 if (in_checked_context) {
1398 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1399 throw new OverflowException ();
1401 return new SByteConstant (target_type, (sbyte) Value, Location);
1402 case BuiltinTypeSpec.Type.Short:
1403 if (in_checked_context) {
1404 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1405 throw new OverflowException ();
1407 return new ShortConstant (target_type, (short) Value, Location);
1408 case BuiltinTypeSpec.Type.UShort:
1409 if (in_checked_context) {
1410 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1411 throw new OverflowException ();
1413 return new UShortConstant (target_type, (ushort) Value, Location);
1414 case BuiltinTypeSpec.Type.Int:
1415 if (in_checked_context) {
1416 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1417 throw new OverflowException ();
1419 return new IntConstant (target_type, (int) Value, Location);
1420 case BuiltinTypeSpec.Type.UInt:
1421 if (in_checked_context) {
1422 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1423 throw new OverflowException ();
1425 return new UIntConstant (target_type, (uint) Value, Location);
1426 case BuiltinTypeSpec.Type.ULong:
1427 if (in_checked_context && Value < 0)
1428 throw new OverflowException ();
1429 return new ULongConstant (target_type, (ulong) Value, Location);
1430 case BuiltinTypeSpec.Type.Float:
1431 return new FloatConstant (target_type, (float) Value, Location);
1432 case BuiltinTypeSpec.Type.Double:
1433 return new DoubleConstant (target_type, (double) Value, Location);
1434 case BuiltinTypeSpec.Type.Char:
1435 if (in_checked_context) {
1436 if (Value < Char.MinValue || Value > Char.MaxValue)
1437 throw new OverflowException ();
1439 return new CharConstant (target_type, (char) Value, Location);
1440 case BuiltinTypeSpec.Type.Decimal:
1441 return new DecimalConstant (target_type, (decimal) Value, Location);
1447 public override Constant ConvertImplicitly (TypeSpec type)
1449 if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) {
1450 return new ULongConstant (type, (ulong) Value, loc);
1453 return base.ConvertImplicitly (type);
1457 public class ULongConstant : IntegralConstant {
1458 public readonly ulong Value;
1460 public ULongConstant (BuiltinTypes types, ulong v, Location loc)
1461 : this (types.ULong, v, loc)
1465 public ULongConstant (TypeSpec type, ulong v, Location loc)
1471 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1476 public override void Emit (EmitContext ec)
1478 ec.EmitLong (unchecked ((long) Value));
1481 public override object GetValue ()
1486 public override long GetValueAsLong ()
1488 return (long) Value;
1491 public override Constant Increment ()
1493 return new ULongConstant (type, checked(Value + 1), loc);
1496 public override bool IsDefaultValue {
1502 public override bool IsNegative {
1508 public override bool IsOneInteger {
1514 public override bool IsZeroInteger {
1515 get { return Value == 0; }
1518 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1520 switch (target_type.BuiltinType) {
1521 case BuiltinTypeSpec.Type.Byte:
1522 if (in_checked_context && Value > Byte.MaxValue)
1523 throw new OverflowException ();
1524 return new ByteConstant (target_type, (byte) Value, Location);
1525 case BuiltinTypeSpec.Type.SByte:
1526 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1527 throw new OverflowException ();
1528 return new SByteConstant (target_type, (sbyte) Value, Location);
1529 case BuiltinTypeSpec.Type.Short:
1530 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1531 throw new OverflowException ();
1532 return new ShortConstant (target_type, (short) Value, Location);
1533 case BuiltinTypeSpec.Type.UShort:
1534 if (in_checked_context && Value > UInt16.MaxValue)
1535 throw new OverflowException ();
1536 return new UShortConstant (target_type, (ushort) Value, Location);
1537 case BuiltinTypeSpec.Type.Int:
1538 if (in_checked_context && Value > UInt32.MaxValue)
1539 throw new OverflowException ();
1540 return new IntConstant (target_type, (int) Value, Location);
1541 case BuiltinTypeSpec.Type.UInt:
1542 if (in_checked_context && Value > UInt32.MaxValue)
1543 throw new OverflowException ();
1544 return new UIntConstant (target_type, (uint) Value, Location);
1545 case BuiltinTypeSpec.Type.Long:
1546 if (in_checked_context && Value > Int64.MaxValue)
1547 throw new OverflowException ();
1548 return new LongConstant (target_type, (long) Value, Location);
1549 case BuiltinTypeSpec.Type.Float:
1550 return new FloatConstant (target_type, (float) Value, Location);
1551 case BuiltinTypeSpec.Type.Double:
1552 return new DoubleConstant (target_type, (double) Value, Location);
1553 case BuiltinTypeSpec.Type.Char:
1554 if (in_checked_context && Value > Char.MaxValue)
1555 throw new OverflowException ();
1556 return new CharConstant (target_type, (char) Value, Location);
1557 case BuiltinTypeSpec.Type.Decimal:
1558 return new DecimalConstant (target_type, (decimal) Value, Location);
1566 public class FloatConstant : Constant {
1567 public readonly float Value;
1569 public FloatConstant (BuiltinTypes types, float v, Location loc)
1570 : this (types.Float, v, loc)
1574 public FloatConstant (TypeSpec type, float v, Location loc)
1578 eclass = ExprClass.Value;
1583 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1588 public override void Emit (EmitContext ec)
1590 ec.Emit (OpCodes.Ldc_R4, Value);
1593 public override object GetValue ()
1598 public override string GetValueAsLiteral ()
1600 return Value.ToString ();
1603 public override long GetValueAsLong ()
1605 throw new NotSupportedException ();
1608 public override bool IsDefaultValue {
1614 public override bool IsNegative {
1620 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1622 switch (target_type.BuiltinType) {
1623 case BuiltinTypeSpec.Type.Byte:
1624 if (in_checked_context) {
1625 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1626 throw new OverflowException ();
1628 return new ByteConstant (target_type, (byte) Value, Location);
1629 case BuiltinTypeSpec.Type.SByte:
1630 if (in_checked_context) {
1631 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1632 throw new OverflowException ();
1634 return new SByteConstant (target_type, (sbyte) Value, Location);
1635 case BuiltinTypeSpec.Type.Short:
1636 if (in_checked_context) {
1637 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1638 throw new OverflowException ();
1640 return new ShortConstant (target_type, (short) Value, Location);
1641 case BuiltinTypeSpec.Type.UShort:
1642 if (in_checked_context) {
1643 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1644 throw new OverflowException ();
1646 return new UShortConstant (target_type, (ushort) Value, Location);
1647 case BuiltinTypeSpec.Type.Int:
1648 if (in_checked_context) {
1649 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1650 throw new OverflowException ();
1652 return new IntConstant (target_type, (int) Value, Location);
1653 case BuiltinTypeSpec.Type.UInt:
1654 if (in_checked_context) {
1655 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1656 throw new OverflowException ();
1658 return new UIntConstant (target_type, (uint) Value, Location);
1659 case BuiltinTypeSpec.Type.Long:
1660 if (in_checked_context) {
1661 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1662 throw new OverflowException ();
1664 return new LongConstant (target_type, (long) Value, Location);
1665 case BuiltinTypeSpec.Type.ULong:
1666 if (in_checked_context) {
1667 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1668 throw new OverflowException ();
1670 return new ULongConstant (target_type, (ulong) Value, Location);
1671 case BuiltinTypeSpec.Type.Double:
1672 return new DoubleConstant (target_type, (double) Value, Location);
1673 case BuiltinTypeSpec.Type.Char:
1674 if (in_checked_context) {
1675 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1676 throw new OverflowException ();
1678 return new CharConstant (target_type, (char) Value, Location);
1679 case BuiltinTypeSpec.Type.Decimal:
1680 return new DecimalConstant (target_type, (decimal) Value, Location);
1688 public class DoubleConstant : Constant
1690 public readonly double Value;
1692 public DoubleConstant (BuiltinTypes types, double v, Location loc)
1693 : this (types.Double, v, loc)
1697 public DoubleConstant (TypeSpec type, double v, Location loc)
1701 eclass = ExprClass.Value;
1706 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1711 public override void Emit (EmitContext ec)
1713 ec.Emit (OpCodes.Ldc_R8, Value);
1716 public override object GetValue ()
1721 public override string GetValueAsLiteral ()
1723 return Value.ToString ();
1726 public override long GetValueAsLong ()
1728 throw new NotSupportedException ();
1731 public override bool IsDefaultValue {
1737 public override bool IsNegative {
1743 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1745 switch (target_type.BuiltinType) {
1746 case BuiltinTypeSpec.Type.Byte:
1747 if (in_checked_context) {
1748 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1749 throw new OverflowException ();
1751 return new ByteConstant (target_type, (byte) Value, Location);
1752 case BuiltinTypeSpec.Type.SByte:
1753 if (in_checked_context) {
1754 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1755 throw new OverflowException ();
1757 return new SByteConstant (target_type, (sbyte) Value, Location);
1758 case BuiltinTypeSpec.Type.Short:
1759 if (in_checked_context) {
1760 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1761 throw new OverflowException ();
1763 return new ShortConstant (target_type, (short) Value, Location);
1764 case BuiltinTypeSpec.Type.UShort:
1765 if (in_checked_context) {
1766 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1767 throw new OverflowException ();
1769 return new UShortConstant (target_type, (ushort) Value, Location);
1770 case BuiltinTypeSpec.Type.Int:
1771 if (in_checked_context) {
1772 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1773 throw new OverflowException ();
1775 return new IntConstant (target_type, (int) Value, Location);
1776 case BuiltinTypeSpec.Type.UInt:
1777 if (in_checked_context) {
1778 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1779 throw new OverflowException ();
1781 return new UIntConstant (target_type, (uint) Value, Location);
1782 case BuiltinTypeSpec.Type.Long:
1783 if (in_checked_context) {
1784 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1785 throw new OverflowException ();
1787 return new LongConstant (target_type, (long) Value, Location);
1788 case BuiltinTypeSpec.Type.ULong:
1789 if (in_checked_context) {
1790 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1791 throw new OverflowException ();
1793 return new ULongConstant (target_type, (ulong) Value, Location);
1794 case BuiltinTypeSpec.Type.Float:
1795 return new FloatConstant (target_type, (float) Value, Location);
1796 case BuiltinTypeSpec.Type.Char:
1797 if (in_checked_context) {
1798 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1799 throw new OverflowException ();
1801 return new CharConstant (target_type, (char) Value, Location);
1802 case BuiltinTypeSpec.Type.Decimal:
1803 return new DecimalConstant (target_type, (decimal) Value, Location);
1811 public class DecimalConstant : Constant {
1812 public readonly decimal Value;
1814 public DecimalConstant (BuiltinTypes types, decimal d, Location loc)
1815 : this (types.Decimal, d, loc)
1819 public DecimalConstant (TypeSpec type, decimal d, Location loc)
1823 eclass = ExprClass.Value;
1828 public override void Emit (EmitContext ec)
1832 int [] words = decimal.GetBits (Value);
1833 int power = (words [3] >> 16) & 0xff;
1836 if (Value <= int.MaxValue && Value >= int.MinValue) {
1837 m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc);
1842 ec.EmitInt ((int) Value);
1843 ec.Emit (OpCodes.Newobj, m);
1847 if (Value <= long.MaxValue && Value >= long.MinValue) {
1848 m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc);
1853 ec.EmitLong ((long) Value);
1854 ec.Emit (OpCodes.Newobj, m);
1859 ec.EmitInt (words [0]);
1860 ec.EmitInt (words [1]);
1861 ec.EmitInt (words [2]);
1864 ec.EmitInt (words [3] >> 31);
1869 m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc);
1871 ec.Emit (OpCodes.Newobj, m);
1875 public override bool IsDefaultValue {
1881 public override bool IsNegative {
1887 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1889 switch (target_type.BuiltinType) {
1890 case BuiltinTypeSpec.Type.SByte:
1891 return new SByteConstant (target_type, (sbyte) Value, loc);
1892 case BuiltinTypeSpec.Type.Byte:
1893 return new ByteConstant (target_type, (byte) Value, loc);
1894 case BuiltinTypeSpec.Type.Short:
1895 return new ShortConstant (target_type, (short) Value, loc);
1896 case BuiltinTypeSpec.Type.UShort:
1897 return new UShortConstant (target_type, (ushort) Value, loc);
1898 case BuiltinTypeSpec.Type.Int:
1899 return new IntConstant (target_type, (int) Value, loc);
1900 case BuiltinTypeSpec.Type.UInt:
1901 return new UIntConstant (target_type, (uint) Value, loc);
1902 case BuiltinTypeSpec.Type.Long:
1903 return new LongConstant (target_type, (long) Value, loc);
1904 case BuiltinTypeSpec.Type.ULong:
1905 return new ULongConstant (target_type, (ulong) Value, loc);
1906 case BuiltinTypeSpec.Type.Char:
1907 return new CharConstant (target_type, (char) Value, loc);
1908 case BuiltinTypeSpec.Type.Float:
1909 return new FloatConstant (target_type, (float) Value, loc);
1910 case BuiltinTypeSpec.Type.Double:
1911 return new DoubleConstant (target_type, (double) Value, loc);
1917 public override object GetValue ()
1922 public override string GetValueAsLiteral ()
1924 return Value.ToString () + "M";
1927 public override long GetValueAsLong ()
1929 throw new NotSupportedException ();
1933 public class StringConstant : Constant {
1934 public readonly string Value;
1936 public StringConstant (BuiltinTypes types, string s, Location loc)
1937 : this (types.String, s, loc)
1941 public StringConstant (TypeSpec type, string s, Location loc)
1945 eclass = ExprClass.Value;
1950 public override object GetValue ()
1955 public override string GetValueAsLiteral ()
1957 // FIXME: Escape the string.
1958 return "\"" + Value + "\"";
1961 public override long GetValueAsLong ()
1963 throw new NotSupportedException ();
1966 public override void Emit (EmitContext ec)
1968 if (Value == null) {
1974 // Use string.Empty for both literals and constants even if
1975 // it's not allowed at language level
1977 if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) {
1978 var string_type = ec.BuiltinTypes.String;
1979 if (ec.CurrentType != string_type) {
1980 var m = ec.Module.PredefinedMembers.StringEmpty.Get ();
1982 ec.Emit (OpCodes.Ldsfld, m);
1988 ec.Emit (OpCodes.Ldstr, Value);
1991 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1994 if (type != targetType)
2000 public override bool IsDefaultValue {
2002 return Value == null;
2006 public override bool IsNegative {
2012 public override bool IsNull {
2014 return IsDefaultValue;
2018 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2025 // Null constant can have its own type, think of `default (Foo)'
2027 public class NullConstant : Constant
2029 public NullConstant (TypeSpec type, Location loc)
2032 eclass = ExprClass.Value;
2036 public override Expression CreateExpressionTree (ResolveContext ec)
2038 if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2039 // Optimized version, also avoids referencing literal internal type
2040 Arguments args = new Arguments (1);
2041 args.Add (new Argument (this));
2042 return CreateExpressionFactoryCall (ec, "Constant", args);
2045 return base.CreateExpressionTree (ec);
2048 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
2050 switch (targetType.BuiltinType) {
2051 case BuiltinTypeSpec.Type.Object:
2052 // Type it as string cast
2053 enc.Encode (rc.Module.Compiler.BuiltinTypes.String);
2054 goto case BuiltinTypeSpec.Type.String;
2055 case BuiltinTypeSpec.Type.String:
2056 case BuiltinTypeSpec.Type.Type:
2057 enc.Encode (byte.MaxValue);
2060 var ac = targetType as ArrayContainer;
2061 if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) {
2062 enc.Encode (uint.MaxValue);
2069 base.EncodeAttributeValue (rc, enc, targetType);
2072 public override void Emit (EmitContext ec)
2076 // Only to make verifier happy
2077 if (type.IsGenericParameter)
2078 ec.Emit (OpCodes.Unbox_Any, type);
2081 public override string ExprClassName {
2083 return GetSignatureForError ();
2087 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2089 if (targetType.IsPointer) {
2090 if (IsLiteral || this is NullPointer)
2091 return new NullPointer (targetType, loc);
2096 // Exlude internal compiler types
2097 if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic)
2100 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2103 if (TypeSpec.IsReferenceType (targetType))
2104 return new NullConstant (targetType, loc);
2106 if (targetType.IsNullableType)
2107 return Nullable.LiftedNull.Create (targetType, loc);
2112 public override Constant ConvertImplicitly (TypeSpec targetType)
2114 return ConvertExplicitly (false, targetType);
2117 public override string GetSignatureForError ()
2122 public override object GetValue ()
2127 public override string GetValueAsLiteral ()
2129 return GetSignatureForError ();
2132 public override long GetValueAsLong ()
2134 throw new NotSupportedException ();
2137 public override bool IsDefaultValue {
2138 get { return true; }
2141 public override bool IsNegative {
2142 get { return false; }
2145 public override bool IsNull {
2146 get { return true; }
2149 public override bool IsZeroInteger {
2150 get { return true; }
2156 // A null constant in a pointer context
2158 class NullPointer : NullConstant
2160 public NullPointer (TypeSpec type, Location loc)
2165 public override Expression CreateExpressionTree (ResolveContext ec)
2167 Error_PointerInsideExpressionTree (ec);
2168 return base.CreateExpressionTree (ec);
2171 public override void Emit (EmitContext ec)
2174 // Emits null pointer
2177 ec.Emit (OpCodes.Conv_U);
2182 /// The value is constant, but when emitted has a side effect. This is
2183 /// used by BitwiseAnd to ensure that the second expression is invoked
2184 /// regardless of the value of the left side.
2186 public class SideEffectConstant : Constant
2188 public readonly Constant value;
2189 Expression side_effect;
2191 public SideEffectConstant (Constant value, Expression side_effect, Location loc)
2196 eclass = ExprClass.Value;
2198 while (side_effect is SideEffectConstant)
2199 side_effect = ((SideEffectConstant) side_effect).side_effect;
2200 this.side_effect = side_effect;
2203 public override bool IsSideEffectFree {
2209 public override object GetValue ()
2211 return value.GetValue ();
2214 public override string GetValueAsLiteral ()
2216 return value.GetValueAsLiteral ();
2219 public override long GetValueAsLong ()
2221 return value.GetValueAsLong ();
2224 public override void Emit (EmitContext ec)
2226 side_effect.EmitSideEffect (ec);
2230 public override void EmitSideEffect (EmitContext ec)
2232 side_effect.EmitSideEffect (ec);
2233 value.EmitSideEffect (ec);
2236 public override bool IsDefaultValue {
2237 get { return value.IsDefaultValue; }
2240 public override bool IsNegative {
2241 get { return value.IsNegative; }
2244 public override bool IsZeroInteger {
2245 get { return value.IsZeroInteger; }
2248 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2250 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2251 if (new_value == null)
2254 var c = new SideEffectConstant (new_value, side_effect, new_value.Location);
2255 c.type = target_type;