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 (), TypeManager.CSharpName (target));
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 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
106 return CreateConstant (type, constant_value, loc);
110 // Returns a constant instance based on Type
112 public static Constant CreateConstant (TypeSpec t, object v, Location loc)
114 return CreateConstantFromValue (t, v, loc);
117 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
119 switch (t.BuiltinType) {
120 case BuiltinTypeSpec.Type.Int:
121 return new IntConstant (t, (int) v, loc);
122 case BuiltinTypeSpec.Type.String:
123 return new StringConstant (t, (string) v, loc);
124 case BuiltinTypeSpec.Type.UInt:
125 return new UIntConstant (t, (uint) v, loc);
126 case BuiltinTypeSpec.Type.Long:
127 return new LongConstant (t, (long) v, loc);
128 case BuiltinTypeSpec.Type.ULong:
129 return new ULongConstant (t, (ulong) v, loc);
130 case BuiltinTypeSpec.Type.Float:
131 return new FloatConstant (t, (float) v, loc);
132 case BuiltinTypeSpec.Type.Double:
133 return new DoubleConstant (t, (double) v, loc);
134 case BuiltinTypeSpec.Type.Short:
135 return new ShortConstant (t, (short) v, loc);
136 case BuiltinTypeSpec.Type.UShort:
137 return new UShortConstant (t, (ushort) v, loc);
138 case BuiltinTypeSpec.Type.SByte:
139 return new SByteConstant (t, (sbyte) v, loc);
140 case BuiltinTypeSpec.Type.Byte:
141 return new ByteConstant (t, (byte) v, loc);
142 case BuiltinTypeSpec.Type.Char:
143 return new CharConstant (t, (char) v, loc);
144 case BuiltinTypeSpec.Type.Bool:
145 return new BoolConstant (t, (bool) v, loc);
146 case BuiltinTypeSpec.Type.Decimal:
147 return new DecimalConstant (t, (decimal) v, loc);
151 var real_type = EnumSpec.GetUnderlyingType (t);
152 return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t);
156 if (t.IsNullableType)
157 return Nullable.LiftedNull.Create (t, loc);
159 if (TypeSpec.IsReferenceType (t))
160 return new NullConstant (t, loc);
164 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ());
170 public override Expression CreateExpressionTree (ResolveContext ec)
172 Arguments args = new Arguments (2);
173 args.Add (new Argument (this));
174 args.Add (new Argument (new TypeOf (type, loc)));
176 return CreateExpressionFactoryCall (ec, "Constant", args);
180 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
181 /// It throws OverflowException
183 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
184 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
186 // This is a custom version of Convert.ChangeType() which works
187 // with the TypeBuilder defined types when compiling corlib.
188 static object ChangeType (object value, TypeSpec targetType, out bool error)
190 IConvertible convert_value = value as IConvertible;
192 if (convert_value == null) {
198 // We cannot rely on build-in type conversions as they are
199 // more limited than what C# supports.
200 // See char -> float/decimal/double conversion
204 switch (targetType.BuiltinType) {
205 case BuiltinTypeSpec.Type.Bool:
206 return convert_value.ToBoolean (nfi);
207 case BuiltinTypeSpec.Type.Byte:
208 return convert_value.ToByte (nfi);
209 case BuiltinTypeSpec.Type.Char:
210 return convert_value.ToChar (nfi);
211 case BuiltinTypeSpec.Type.Short:
212 return convert_value.ToInt16 (nfi);
213 case BuiltinTypeSpec.Type.Int:
214 return convert_value.ToInt32 (nfi);
215 case BuiltinTypeSpec.Type.Long:
216 return convert_value.ToInt64 (nfi);
217 case BuiltinTypeSpec.Type.SByte:
218 return convert_value.ToSByte (nfi);
219 case BuiltinTypeSpec.Type.Decimal:
220 if (convert_value.GetType () == typeof (char))
221 return (decimal) convert_value.ToInt32 (nfi);
222 return convert_value.ToDecimal (nfi);
223 case BuiltinTypeSpec.Type.Double:
224 if (convert_value.GetType () == typeof (char))
225 return (double) convert_value.ToInt32 (nfi);
226 return convert_value.ToDouble (nfi);
227 case BuiltinTypeSpec.Type.Float:
228 if (convert_value.GetType () == typeof (char))
229 return (float) convert_value.ToInt32 (nfi);
230 return convert_value.ToSingle (nfi);
231 case BuiltinTypeSpec.Type.String:
232 return convert_value.ToString (nfi);
233 case BuiltinTypeSpec.Type.UShort:
234 return convert_value.ToUInt16 (nfi);
235 case BuiltinTypeSpec.Type.UInt:
236 return convert_value.ToUInt32 (nfi);
237 case BuiltinTypeSpec.Type.ULong:
238 return convert_value.ToUInt64 (nfi);
239 case BuiltinTypeSpec.Type.Object:
249 protected override Expression DoResolve (ResolveContext rc)
255 // Attempts to do a compile-time folding of a constant cast and handles
256 // error reporting for constant overlows only, on normal conversion
257 // errors returns null
259 public Constant Reduce (ResolveContext ec, TypeSpec target_type)
262 return TryReduceConstant (ec, target_type);
263 } catch (OverflowException) {
264 if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
265 ec.Report.Error (221, loc,
266 "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
267 GetValueAsLiteral (), target_type.GetSignatureForError ());
269 Error_ValueCannotBeConverted (ec, target_type, false);
272 return New.Constantify (target_type, loc);
276 public Constant TryReduce (ResolveContext rc, TypeSpec targetType)
279 return TryReduceConstant (rc, targetType);
280 } catch (OverflowException) {
285 Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type)
287 if (Type == target_type) {
289 // Reducing literal value produces a new constant. Syntactically 10 is not same as (int)10
292 return CreateConstantFromValue (target_type, GetValue (), loc);
298 if (target_type.IsEnum) {
299 c = TryReduceConstant (ec, EnumSpec.GetUnderlyingType (target_type));
303 return new EnumConstant (c, target_type);
306 return ConvertExplicitly (ec.ConstantCheckState, target_type);
310 /// Need to pass type as the constant can require a boxing
311 /// and in such case no optimization is possible
313 public bool IsDefaultInitializer (TypeSpec type)
316 return IsDefaultValue;
318 return this is NullLiteral;
321 public abstract bool IsDefaultValue {
325 public abstract bool IsNegative {
330 // When constant is declared as literal
332 public virtual bool IsLiteral {
333 get { return false; }
336 public virtual bool IsOneInteger {
337 get { return false; }
340 public override bool IsSideEffectFree {
347 // Returns true iff 1) the stack type of this is one of Object,
348 // int32, int64 and 2) this == 0 or this == null.
350 public virtual bool IsZeroInteger {
351 get { return false; }
354 public override void EmitSideEffect (EmitContext ec)
359 public sealed override Expression Clone (CloneContext clonectx)
361 // No cloning is not needed for constants
365 protected override void CloneTo (CloneContext clonectx, Expression target)
367 throw new NotSupportedException ("should not be reached");
370 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
373 return base.MakeExpression (ctx);
375 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
379 public new bool Resolve (ResolveContext rc)
381 // It exists only as hint not to call Resolve on constants
386 public abstract class IntegralConstant : Constant
388 protected IntegralConstant (TypeSpec type, Location loc)
392 eclass = ExprClass.Value;
395 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
398 ConvertExplicitly (true, target);
399 base.Error_ValueCannotBeConverted (ec, target, expl);
403 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
404 GetValue ().ToString (), TypeManager.CSharpName (target));
408 public override string GetValueAsLiteral ()
410 return GetValue ().ToString ();
413 public abstract Constant Increment ();
416 public class BoolConstant : Constant {
417 public readonly bool Value;
419 public BoolConstant (BuiltinTypes types, bool val, Location loc)
420 : this (types.Bool, val, loc)
424 public BoolConstant (TypeSpec type, bool val, Location loc)
427 eclass = ExprClass.Value;
433 public override object GetValue ()
435 return (object) Value;
438 public override string GetValueAsLiteral ()
440 return Value ? "true" : "false";
443 public override long GetValueAsLong ()
445 return Value ? 1 : 0;
448 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
453 public override void Emit (EmitContext ec)
461 public override bool IsDefaultValue {
467 public override bool IsNegative {
473 public override bool IsZeroInteger {
474 get { return Value == false; }
477 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
484 public class ByteConstant : IntegralConstant
486 public readonly byte Value;
488 public ByteConstant (BuiltinTypes types, byte v, Location loc)
489 : this (types.Byte, v, loc)
493 public ByteConstant (TypeSpec type, byte v, Location loc)
499 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
504 public override void Emit (EmitContext ec)
509 public override object GetValue ()
514 public override long GetValueAsLong ()
519 public override Constant Increment ()
521 return new ByteConstant (type, checked ((byte)(Value + 1)), loc);
524 public override bool IsDefaultValue {
530 public override bool IsOneInteger {
536 public override bool IsNegative {
542 public override bool IsZeroInteger {
543 get { return Value == 0; }
546 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
548 switch (target_type.BuiltinType) {
549 case BuiltinTypeSpec.Type.SByte:
550 if (in_checked_context){
551 if (Value > SByte.MaxValue)
552 throw new OverflowException ();
554 return new SByteConstant (target_type, (sbyte) Value, Location);
555 case BuiltinTypeSpec.Type.Short:
556 return new ShortConstant (target_type, (short) Value, Location);
557 case BuiltinTypeSpec.Type.UShort:
558 return new UShortConstant (target_type, (ushort) Value, Location);
559 case BuiltinTypeSpec.Type.Int:
560 return new IntConstant (target_type, (int) Value, Location);
561 case BuiltinTypeSpec.Type.UInt:
562 return new UIntConstant (target_type, (uint) Value, Location);
563 case BuiltinTypeSpec.Type.Long:
564 return new LongConstant (target_type, (long) Value, Location);
565 case BuiltinTypeSpec.Type.ULong:
566 return new ULongConstant (target_type, (ulong) Value, Location);
567 case BuiltinTypeSpec.Type.Float:
568 return new FloatConstant (target_type, (float) Value, Location);
569 case BuiltinTypeSpec.Type.Double:
570 return new DoubleConstant (target_type, (double) Value, Location);
571 case BuiltinTypeSpec.Type.Char:
572 return new CharConstant (target_type, (char) Value, Location);
573 case BuiltinTypeSpec.Type.Decimal:
574 return new DecimalConstant (target_type, (decimal) Value, Location);
582 public class CharConstant : Constant {
583 public readonly char Value;
585 public CharConstant (BuiltinTypes types, char v, Location loc)
586 : this (types.Char, v, loc)
590 public CharConstant (TypeSpec type, char v, Location loc)
594 eclass = ExprClass.Value;
599 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
601 enc.Encode ((ushort) Value);
604 public override void Emit (EmitContext ec)
609 static string descape (char c)
635 return c.ToString ();
638 public override object GetValue ()
643 public override long GetValueAsLong ()
648 public override string GetValueAsLiteral ()
650 return "\"" + descape (Value) + "\"";
653 public override bool IsDefaultValue {
659 public override bool IsNegative {
665 public override bool IsZeroInteger {
666 get { return Value == '\0'; }
669 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
671 switch (target_type.BuiltinType) {
672 case BuiltinTypeSpec.Type.Byte:
673 if (in_checked_context) {
674 if (Value < Byte.MinValue || Value > Byte.MaxValue)
675 throw new OverflowException ();
677 return new ByteConstant (target_type, (byte) Value, Location);
678 case BuiltinTypeSpec.Type.SByte:
679 if (in_checked_context) {
680 if (Value > SByte.MaxValue)
681 throw new OverflowException ();
683 return new SByteConstant (target_type, (sbyte) Value, Location);
685 case BuiltinTypeSpec.Type.Short:
686 if (in_checked_context) {
687 if (Value > Int16.MaxValue)
688 throw new OverflowException ();
690 return new ShortConstant (target_type, (short) Value, Location);
691 case BuiltinTypeSpec.Type.Int:
692 return new IntConstant (target_type, (int) Value, Location);
693 case BuiltinTypeSpec.Type.UInt:
694 return new UIntConstant (target_type, (uint) Value, Location);
695 case BuiltinTypeSpec.Type.Long:
696 return new LongConstant (target_type, (long) Value, Location);
697 case BuiltinTypeSpec.Type.ULong:
698 return new ULongConstant (target_type, (ulong) Value, Location);
699 case BuiltinTypeSpec.Type.Float:
700 return new FloatConstant (target_type, (float) Value, Location);
701 case BuiltinTypeSpec.Type.Double:
702 return new DoubleConstant (target_type, (double) Value, Location);
703 case BuiltinTypeSpec.Type.Decimal:
704 return new DecimalConstant (target_type, (decimal) Value, Location);
712 public class SByteConstant : IntegralConstant
714 public readonly sbyte Value;
716 public SByteConstant (BuiltinTypes types, sbyte v, Location loc)
717 : this (types.SByte, v, loc)
721 public SByteConstant (TypeSpec type, sbyte v, Location loc)
727 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
732 public override void Emit (EmitContext ec)
737 public override object GetValue ()
742 public override long GetValueAsLong ()
747 public override Constant Increment ()
749 return new SByteConstant (type, checked((sbyte)(Value + 1)), loc);
752 public override bool IsDefaultValue {
758 public override bool IsNegative {
764 public override bool IsOneInteger {
770 public override bool IsZeroInteger {
771 get { return Value == 0; }
774 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
776 switch (target_type.BuiltinType) {
777 case BuiltinTypeSpec.Type.Byte:
778 if (in_checked_context && Value < 0)
779 throw new OverflowException ();
780 return new ByteConstant (target_type, (byte) Value, Location);
781 case BuiltinTypeSpec.Type.Short:
782 return new ShortConstant (target_type, (short) Value, Location);
783 case BuiltinTypeSpec.Type.UShort:
784 if (in_checked_context && Value < 0)
785 throw new OverflowException ();
786 return new UShortConstant (target_type, (ushort) Value, Location);
787 case BuiltinTypeSpec.Type.Int:
788 return new IntConstant (target_type, (int) Value, Location);
789 case BuiltinTypeSpec.Type.UInt:
790 if (in_checked_context && Value < 0)
791 throw new OverflowException ();
792 return new UIntConstant (target_type, (uint) Value, Location);
793 case BuiltinTypeSpec.Type.Long:
794 return new LongConstant (target_type, (long) Value, Location);
795 case BuiltinTypeSpec.Type.ULong:
796 if (in_checked_context && Value < 0)
797 throw new OverflowException ();
798 return new ULongConstant (target_type, (ulong) Value, Location);
799 case BuiltinTypeSpec.Type.Float:
800 return new FloatConstant (target_type, (float) Value, Location);
801 case BuiltinTypeSpec.Type.Double:
802 return new DoubleConstant (target_type, (double) Value, Location);
803 case BuiltinTypeSpec.Type.Char:
804 if (in_checked_context && Value < 0)
805 throw new OverflowException ();
806 return new CharConstant (target_type, (char) Value, Location);
807 case BuiltinTypeSpec.Type.Decimal:
808 return new DecimalConstant (target_type, (decimal) Value, Location);
816 public class ShortConstant : IntegralConstant {
817 public readonly short Value;
819 public ShortConstant (BuiltinTypes types, short v, Location loc)
820 : this (types.Short, v, loc)
824 public ShortConstant (TypeSpec type, short v, Location loc)
830 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
835 public override void Emit (EmitContext ec)
840 public override object GetValue ()
845 public override long GetValueAsLong ()
850 public override Constant Increment ()
852 return new ShortConstant (type, checked((short)(Value + 1)), loc);
855 public override bool IsDefaultValue {
861 public override bool IsZeroInteger {
862 get { return Value == 0; }
865 public override bool IsNegative {
871 public override bool IsOneInteger {
877 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
879 switch (target_type.BuiltinType) {
880 case BuiltinTypeSpec.Type.Byte:
881 if (in_checked_context) {
882 if (Value < Byte.MinValue || Value > Byte.MaxValue)
883 throw new OverflowException ();
885 return new ByteConstant (target_type, (byte) Value, Location);
886 case BuiltinTypeSpec.Type.SByte:
887 if (in_checked_context) {
888 if (Value < SByte.MinValue || Value > SByte.MaxValue)
889 throw new OverflowException ();
891 return new SByteConstant (target_type, (sbyte) Value, Location);
892 case BuiltinTypeSpec.Type.UShort:
893 if (in_checked_context && Value < 0)
894 throw new OverflowException ();
896 return new UShortConstant (target_type, (ushort) Value, Location);
897 case BuiltinTypeSpec.Type.Int:
898 return new IntConstant (target_type, (int) Value, Location);
899 case BuiltinTypeSpec.Type.UInt:
900 if (in_checked_context && Value < 0)
901 throw new OverflowException ();
902 return new UIntConstant (target_type, (uint) Value, Location);
903 case BuiltinTypeSpec.Type.Long:
904 return new LongConstant (target_type, (long) Value, Location);
905 case BuiltinTypeSpec.Type.ULong:
906 if (in_checked_context && Value < 0)
907 throw new OverflowException ();
908 return new ULongConstant (target_type, (ulong) Value, Location);
909 case BuiltinTypeSpec.Type.Float:
910 return new FloatConstant (target_type, (float) Value, Location);
911 case BuiltinTypeSpec.Type.Double:
912 return new DoubleConstant (target_type, (double) Value, Location);
913 case BuiltinTypeSpec.Type.Char:
914 if (in_checked_context) {
915 if (Value < Char.MinValue)
916 throw new OverflowException ();
918 return new CharConstant (target_type, (char) Value, Location);
919 case BuiltinTypeSpec.Type.Decimal:
920 return new DecimalConstant (target_type, (decimal) Value, Location);
928 public class UShortConstant : IntegralConstant
930 public readonly ushort Value;
932 public UShortConstant (BuiltinTypes types, ushort v, Location loc)
933 : this (types.UShort, v, loc)
937 public UShortConstant (TypeSpec type, ushort v, Location loc)
943 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
948 public override void Emit (EmitContext ec)
953 public override object GetValue ()
958 public override long GetValueAsLong ()
963 public override Constant Increment ()
965 return new UShortConstant (type, checked((ushort)(Value + 1)), loc);
968 public override bool IsDefaultValue {
974 public override bool IsNegative {
980 public override bool IsOneInteger {
986 public override bool IsZeroInteger {
987 get { return Value == 0; }
990 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
992 switch (target_type.BuiltinType) {
993 case BuiltinTypeSpec.Type.Byte:
994 if (in_checked_context) {
995 if (Value > Byte.MaxValue)
996 throw new OverflowException ();
998 return new ByteConstant (target_type, (byte) Value, Location);
999 case BuiltinTypeSpec.Type.SByte:
1000 if (in_checked_context) {
1001 if (Value > SByte.MaxValue)
1002 throw new OverflowException ();
1004 return new SByteConstant (target_type, (sbyte) Value, Location);
1005 case BuiltinTypeSpec.Type.Short:
1006 if (in_checked_context) {
1007 if (Value > Int16.MaxValue)
1008 throw new OverflowException ();
1010 return new ShortConstant (target_type, (short) Value, Location);
1011 case BuiltinTypeSpec.Type.Int:
1012 return new IntConstant (target_type, (int) Value, Location);
1013 case BuiltinTypeSpec.Type.UInt:
1014 return new UIntConstant (target_type, (uint) Value, Location);
1015 case BuiltinTypeSpec.Type.Long:
1016 return new LongConstant (target_type, (long) Value, Location);
1017 case BuiltinTypeSpec.Type.ULong:
1018 return new ULongConstant (target_type, (ulong) Value, Location);
1019 case BuiltinTypeSpec.Type.Float:
1020 return new FloatConstant (target_type, (float) Value, Location);
1021 case BuiltinTypeSpec.Type.Double:
1022 return new DoubleConstant (target_type, (double) Value, Location);
1023 case BuiltinTypeSpec.Type.Char:
1024 if (in_checked_context) {
1025 if (Value > Char.MaxValue)
1026 throw new OverflowException ();
1028 return new CharConstant (target_type, (char) Value, Location);
1029 case BuiltinTypeSpec.Type.Decimal:
1030 return new DecimalConstant (target_type, (decimal) Value, Location);
1037 public class IntConstant : IntegralConstant
1039 public readonly int Value;
1041 public IntConstant (BuiltinTypes types, int v, Location loc)
1042 : this (types.Int, v, loc)
1046 public IntConstant (TypeSpec type, int v, Location loc)
1052 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1057 public override void Emit (EmitContext ec)
1062 public override object GetValue ()
1067 public override long GetValueAsLong ()
1072 public override Constant Increment ()
1074 return new IntConstant (type, checked(Value + 1), loc);
1077 public override bool IsDefaultValue {
1083 public override bool IsNegative {
1089 public override bool IsOneInteger {
1095 public override bool IsZeroInteger {
1096 get { return Value == 0; }
1099 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1101 switch (target_type.BuiltinType) {
1102 case BuiltinTypeSpec.Type.Byte:
1103 if (in_checked_context) {
1104 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1105 throw new OverflowException ();
1107 return new ByteConstant (target_type, (byte) Value, Location);
1108 case BuiltinTypeSpec.Type.SByte:
1109 if (in_checked_context) {
1110 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1111 throw new OverflowException ();
1113 return new SByteConstant (target_type, (sbyte) Value, Location);
1114 case BuiltinTypeSpec.Type.Short:
1115 if (in_checked_context) {
1116 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1117 throw new OverflowException ();
1119 return new ShortConstant (target_type, (short) Value, Location);
1120 case BuiltinTypeSpec.Type.UShort:
1121 if (in_checked_context) {
1122 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1123 throw new OverflowException ();
1125 return new UShortConstant (target_type, (ushort) Value, Location);
1126 case BuiltinTypeSpec.Type.UInt:
1127 if (in_checked_context) {
1128 if (Value < UInt32.MinValue)
1129 throw new OverflowException ();
1131 return new UIntConstant (target_type, (uint) Value, Location);
1132 case BuiltinTypeSpec.Type.Long:
1133 return new LongConstant (target_type, (long) Value, Location);
1134 case BuiltinTypeSpec.Type.ULong:
1135 if (in_checked_context && Value < 0)
1136 throw new OverflowException ();
1137 return new ULongConstant (target_type, (ulong) Value, Location);
1138 case BuiltinTypeSpec.Type.Float:
1139 return new FloatConstant (target_type, (float) Value, Location);
1140 case BuiltinTypeSpec.Type.Double:
1141 return new DoubleConstant (target_type, (double) Value, Location);
1142 case BuiltinTypeSpec.Type.Char:
1143 if (in_checked_context) {
1144 if (Value < Char.MinValue || Value > Char.MaxValue)
1145 throw new OverflowException ();
1147 return new CharConstant (target_type, (char) Value, Location);
1148 case BuiltinTypeSpec.Type.Decimal:
1149 return new DecimalConstant (target_type, (decimal) Value, Location);
1155 public override Constant ConvertImplicitly (TypeSpec type)
1157 if (this.type == type)
1160 Constant c = TryImplicitIntConversion (type);
1162 return c; //.Resolve (rc);
1164 return base.ConvertImplicitly (type);
1168 /// Attempts to perform an implicit constant conversion of the IntConstant
1169 /// into a different data type using casts (See Implicit Constant
1170 /// Expression Conversions)
1172 Constant TryImplicitIntConversion (TypeSpec target_type)
1174 switch (target_type.BuiltinType) {
1175 case BuiltinTypeSpec.Type.SByte:
1176 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1177 return new SByteConstant (target_type, (sbyte) Value, loc);
1179 case BuiltinTypeSpec.Type.Byte:
1180 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1181 return new ByteConstant (target_type, (byte) Value, loc);
1183 case BuiltinTypeSpec.Type.Short:
1184 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1185 return new ShortConstant (target_type, (short) Value, loc);
1187 case BuiltinTypeSpec.Type.UShort:
1188 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1189 return new UShortConstant (target_type, (ushort) Value, loc);
1191 case BuiltinTypeSpec.Type.UInt:
1193 return new UIntConstant (target_type, (uint) Value, loc);
1195 case BuiltinTypeSpec.Type.ULong:
1197 // we can optimize this case: a positive int32
1198 // always fits on a uint64. But we need an opcode
1202 return new ULongConstant (target_type, (ulong) Value, loc);
1204 case BuiltinTypeSpec.Type.Double:
1205 return new DoubleConstant (target_type, (double) Value, loc);
1206 case BuiltinTypeSpec.Type.Float:
1207 return new FloatConstant (target_type, (float) Value, loc);
1214 public class UIntConstant : IntegralConstant {
1215 public readonly uint Value;
1217 public UIntConstant (BuiltinTypes types, uint v, Location loc)
1218 : this (types.UInt, v, loc)
1222 public UIntConstant (TypeSpec type, uint v, Location loc)
1228 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1233 public override void Emit (EmitContext ec)
1235 ec.EmitInt (unchecked ((int) Value));
1238 public override object GetValue ()
1243 public override long GetValueAsLong ()
1248 public override Constant Increment ()
1250 return new UIntConstant (type, checked(Value + 1), loc);
1253 public override bool IsDefaultValue {
1259 public override bool IsNegative {
1265 public override bool IsOneInteger {
1271 public override bool IsZeroInteger {
1272 get { return Value == 0; }
1275 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1277 switch (target_type.BuiltinType) {
1278 case BuiltinTypeSpec.Type.Byte:
1279 if (in_checked_context) {
1280 if (Value < 0 || Value > byte.MaxValue)
1281 throw new OverflowException ();
1283 return new ByteConstant (target_type, (byte) Value, Location);
1284 case BuiltinTypeSpec.Type.SByte:
1285 if (in_checked_context) {
1286 if (Value > SByte.MaxValue)
1287 throw new OverflowException ();
1289 return new SByteConstant (target_type, (sbyte) Value, Location);
1290 case BuiltinTypeSpec.Type.Short:
1291 if (in_checked_context) {
1292 if (Value > Int16.MaxValue)
1293 throw new OverflowException ();
1295 return new ShortConstant (target_type, (short) Value, Location);
1296 case BuiltinTypeSpec.Type.UShort:
1297 if (in_checked_context) {
1298 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1299 throw new OverflowException ();
1301 return new UShortConstant (target_type, (ushort) Value, Location);
1302 case BuiltinTypeSpec.Type.Int:
1303 if (in_checked_context) {
1304 if (Value > Int32.MaxValue)
1305 throw new OverflowException ();
1307 return new IntConstant (target_type, (int) Value, Location);
1308 case BuiltinTypeSpec.Type.Long:
1309 return new LongConstant (target_type, (long) Value, Location);
1310 case BuiltinTypeSpec.Type.ULong:
1311 return new ULongConstant (target_type, (ulong) Value, Location);
1312 case BuiltinTypeSpec.Type.Float:
1313 return new FloatConstant (target_type, (float) Value, Location);
1314 case BuiltinTypeSpec.Type.Double:
1315 return new DoubleConstant (target_type, (double) Value, Location);
1316 case BuiltinTypeSpec.Type.Char:
1317 if (in_checked_context) {
1318 if (Value < Char.MinValue || Value > Char.MaxValue)
1319 throw new OverflowException ();
1321 return new CharConstant (target_type, (char) Value, Location);
1322 case BuiltinTypeSpec.Type.Decimal:
1323 return new DecimalConstant (target_type, (decimal) Value, Location);
1331 public class LongConstant : IntegralConstant {
1332 public readonly long Value;
1334 public LongConstant (BuiltinTypes types, long v, Location loc)
1335 : this (types.Long, v, loc)
1339 public LongConstant (TypeSpec type, long v, Location loc)
1345 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1350 public override void Emit (EmitContext ec)
1352 ec.EmitLong (Value);
1355 public override object GetValue ()
1360 public override long GetValueAsLong ()
1365 public override Constant Increment ()
1367 return new LongConstant (type, checked(Value + 1), loc);
1370 public override bool IsDefaultValue {
1376 public override bool IsNegative {
1382 public override bool IsOneInteger {
1388 public override bool IsZeroInteger {
1389 get { return Value == 0; }
1392 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1394 switch (target_type.BuiltinType) {
1395 case BuiltinTypeSpec.Type.Byte:
1396 if (in_checked_context) {
1397 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1398 throw new OverflowException ();
1400 return new ByteConstant (target_type, (byte) Value, Location);
1401 case BuiltinTypeSpec.Type.SByte:
1402 if (in_checked_context) {
1403 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1404 throw new OverflowException ();
1406 return new SByteConstant (target_type, (sbyte) Value, Location);
1407 case BuiltinTypeSpec.Type.Short:
1408 if (in_checked_context) {
1409 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1410 throw new OverflowException ();
1412 return new ShortConstant (target_type, (short) Value, Location);
1413 case BuiltinTypeSpec.Type.UShort:
1414 if (in_checked_context) {
1415 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1416 throw new OverflowException ();
1418 return new UShortConstant (target_type, (ushort) Value, Location);
1419 case BuiltinTypeSpec.Type.Int:
1420 if (in_checked_context) {
1421 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1422 throw new OverflowException ();
1424 return new IntConstant (target_type, (int) Value, Location);
1425 case BuiltinTypeSpec.Type.UInt:
1426 if (in_checked_context) {
1427 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1428 throw new OverflowException ();
1430 return new UIntConstant (target_type, (uint) Value, Location);
1431 case BuiltinTypeSpec.Type.ULong:
1432 if (in_checked_context && Value < 0)
1433 throw new OverflowException ();
1434 return new ULongConstant (target_type, (ulong) Value, Location);
1435 case BuiltinTypeSpec.Type.Float:
1436 return new FloatConstant (target_type, (float) Value, Location);
1437 case BuiltinTypeSpec.Type.Double:
1438 return new DoubleConstant (target_type, (double) Value, Location);
1439 case BuiltinTypeSpec.Type.Char:
1440 if (in_checked_context) {
1441 if (Value < Char.MinValue || Value > Char.MaxValue)
1442 throw new OverflowException ();
1444 return new CharConstant (target_type, (char) Value, Location);
1445 case BuiltinTypeSpec.Type.Decimal:
1446 return new DecimalConstant (target_type, (decimal) Value, Location);
1452 public override Constant ConvertImplicitly (TypeSpec type)
1454 if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) {
1455 return new ULongConstant (type, (ulong) Value, loc);
1458 return base.ConvertImplicitly (type);
1462 public class ULongConstant : IntegralConstant {
1463 public readonly ulong Value;
1465 public ULongConstant (BuiltinTypes types, ulong v, Location loc)
1466 : this (types.ULong, v, loc)
1470 public ULongConstant (TypeSpec type, ulong v, Location loc)
1476 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1481 public override void Emit (EmitContext ec)
1483 ec.EmitLong (unchecked ((long) Value));
1486 public override object GetValue ()
1491 public override long GetValueAsLong ()
1493 return (long) Value;
1496 public override Constant Increment ()
1498 return new ULongConstant (type, checked(Value + 1), loc);
1501 public override bool IsDefaultValue {
1507 public override bool IsNegative {
1513 public override bool IsOneInteger {
1519 public override bool IsZeroInteger {
1520 get { return Value == 0; }
1523 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1525 switch (target_type.BuiltinType) {
1526 case BuiltinTypeSpec.Type.Byte:
1527 if (in_checked_context && Value > Byte.MaxValue)
1528 throw new OverflowException ();
1529 return new ByteConstant (target_type, (byte) Value, Location);
1530 case BuiltinTypeSpec.Type.SByte:
1531 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1532 throw new OverflowException ();
1533 return new SByteConstant (target_type, (sbyte) Value, Location);
1534 case BuiltinTypeSpec.Type.Short:
1535 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1536 throw new OverflowException ();
1537 return new ShortConstant (target_type, (short) Value, Location);
1538 case BuiltinTypeSpec.Type.UShort:
1539 if (in_checked_context && Value > UInt16.MaxValue)
1540 throw new OverflowException ();
1541 return new UShortConstant (target_type, (ushort) Value, Location);
1542 case BuiltinTypeSpec.Type.Int:
1543 if (in_checked_context && Value > UInt32.MaxValue)
1544 throw new OverflowException ();
1545 return new IntConstant (target_type, (int) Value, Location);
1546 case BuiltinTypeSpec.Type.UInt:
1547 if (in_checked_context && Value > UInt32.MaxValue)
1548 throw new OverflowException ();
1549 return new UIntConstant (target_type, (uint) Value, Location);
1550 case BuiltinTypeSpec.Type.Long:
1551 if (in_checked_context && Value > Int64.MaxValue)
1552 throw new OverflowException ();
1553 return new LongConstant (target_type, (long) Value, Location);
1554 case BuiltinTypeSpec.Type.Float:
1555 return new FloatConstant (target_type, (float) Value, Location);
1556 case BuiltinTypeSpec.Type.Double:
1557 return new DoubleConstant (target_type, (double) Value, Location);
1558 case BuiltinTypeSpec.Type.Char:
1559 if (in_checked_context && Value > Char.MaxValue)
1560 throw new OverflowException ();
1561 return new CharConstant (target_type, (char) Value, Location);
1562 case BuiltinTypeSpec.Type.Decimal:
1563 return new DecimalConstant (target_type, (decimal) Value, Location);
1571 public class FloatConstant : Constant {
1572 public readonly float Value;
1574 public FloatConstant (BuiltinTypes types, float v, Location loc)
1575 : this (types.Float, v, loc)
1579 public FloatConstant (TypeSpec type, float v, Location loc)
1583 eclass = ExprClass.Value;
1588 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1593 public override void Emit (EmitContext ec)
1595 ec.Emit (OpCodes.Ldc_R4, Value);
1598 public override object GetValue ()
1603 public override string GetValueAsLiteral ()
1605 return Value.ToString ();
1608 public override long GetValueAsLong ()
1610 throw new NotSupportedException ();
1613 public override bool IsDefaultValue {
1619 public override bool IsNegative {
1625 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1627 switch (target_type.BuiltinType) {
1628 case BuiltinTypeSpec.Type.Byte:
1629 if (in_checked_context) {
1630 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1631 throw new OverflowException ();
1633 return new ByteConstant (target_type, (byte) Value, Location);
1634 case BuiltinTypeSpec.Type.SByte:
1635 if (in_checked_context) {
1636 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1637 throw new OverflowException ();
1639 return new SByteConstant (target_type, (sbyte) Value, Location);
1640 case BuiltinTypeSpec.Type.Short:
1641 if (in_checked_context) {
1642 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1643 throw new OverflowException ();
1645 return new ShortConstant (target_type, (short) Value, Location);
1646 case BuiltinTypeSpec.Type.UShort:
1647 if (in_checked_context) {
1648 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1649 throw new OverflowException ();
1651 return new UShortConstant (target_type, (ushort) Value, Location);
1652 case BuiltinTypeSpec.Type.Int:
1653 if (in_checked_context) {
1654 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1655 throw new OverflowException ();
1657 return new IntConstant (target_type, (int) Value, Location);
1658 case BuiltinTypeSpec.Type.UInt:
1659 if (in_checked_context) {
1660 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1661 throw new OverflowException ();
1663 return new UIntConstant (target_type, (uint) Value, Location);
1664 case BuiltinTypeSpec.Type.Long:
1665 if (in_checked_context) {
1666 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1667 throw new OverflowException ();
1669 return new LongConstant (target_type, (long) Value, Location);
1670 case BuiltinTypeSpec.Type.ULong:
1671 if (in_checked_context) {
1672 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1673 throw new OverflowException ();
1675 return new ULongConstant (target_type, (ulong) Value, Location);
1676 case BuiltinTypeSpec.Type.Double:
1677 return new DoubleConstant (target_type, (double) Value, Location);
1678 case BuiltinTypeSpec.Type.Char:
1679 if (in_checked_context) {
1680 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1681 throw new OverflowException ();
1683 return new CharConstant (target_type, (char) Value, Location);
1684 case BuiltinTypeSpec.Type.Decimal:
1685 return new DecimalConstant (target_type, (decimal) Value, Location);
1693 public class DoubleConstant : Constant
1695 public readonly double Value;
1697 public DoubleConstant (BuiltinTypes types, double v, Location loc)
1698 : this (types.Double, v, loc)
1702 public DoubleConstant (TypeSpec type, double v, Location loc)
1706 eclass = ExprClass.Value;
1711 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1716 public override void Emit (EmitContext ec)
1718 ec.Emit (OpCodes.Ldc_R8, Value);
1721 public override object GetValue ()
1726 public override string GetValueAsLiteral ()
1728 return Value.ToString ();
1731 public override long GetValueAsLong ()
1733 throw new NotSupportedException ();
1736 public override bool IsDefaultValue {
1742 public override bool IsNegative {
1748 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1750 switch (target_type.BuiltinType) {
1751 case BuiltinTypeSpec.Type.Byte:
1752 if (in_checked_context) {
1753 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1754 throw new OverflowException ();
1756 return new ByteConstant (target_type, (byte) Value, Location);
1757 case BuiltinTypeSpec.Type.SByte:
1758 if (in_checked_context) {
1759 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1760 throw new OverflowException ();
1762 return new SByteConstant (target_type, (sbyte) Value, Location);
1763 case BuiltinTypeSpec.Type.Short:
1764 if (in_checked_context) {
1765 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1766 throw new OverflowException ();
1768 return new ShortConstant (target_type, (short) Value, Location);
1769 case BuiltinTypeSpec.Type.UShort:
1770 if (in_checked_context) {
1771 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1772 throw new OverflowException ();
1774 return new UShortConstant (target_type, (ushort) Value, Location);
1775 case BuiltinTypeSpec.Type.Int:
1776 if (in_checked_context) {
1777 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1778 throw new OverflowException ();
1780 return new IntConstant (target_type, (int) Value, Location);
1781 case BuiltinTypeSpec.Type.UInt:
1782 if (in_checked_context) {
1783 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1784 throw new OverflowException ();
1786 return new UIntConstant (target_type, (uint) Value, Location);
1787 case BuiltinTypeSpec.Type.Long:
1788 if (in_checked_context) {
1789 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1790 throw new OverflowException ();
1792 return new LongConstant (target_type, (long) Value, Location);
1793 case BuiltinTypeSpec.Type.ULong:
1794 if (in_checked_context) {
1795 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1796 throw new OverflowException ();
1798 return new ULongConstant (target_type, (ulong) Value, Location);
1799 case BuiltinTypeSpec.Type.Float:
1800 return new FloatConstant (target_type, (float) Value, Location);
1801 case BuiltinTypeSpec.Type.Char:
1802 if (in_checked_context) {
1803 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1804 throw new OverflowException ();
1806 return new CharConstant (target_type, (char) Value, Location);
1807 case BuiltinTypeSpec.Type.Decimal:
1808 return new DecimalConstant (target_type, (decimal) Value, Location);
1816 public class DecimalConstant : Constant {
1817 public readonly decimal Value;
1819 public DecimalConstant (BuiltinTypes types, decimal d, Location loc)
1820 : this (types.Decimal, d, loc)
1824 public DecimalConstant (TypeSpec type, decimal d, Location loc)
1828 eclass = ExprClass.Value;
1833 public override void Emit (EmitContext ec)
1837 int [] words = decimal.GetBits (Value);
1838 int power = (words [3] >> 16) & 0xff;
1841 if (Value <= int.MaxValue && Value >= int.MinValue) {
1842 m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc);
1847 ec.EmitInt ((int) Value);
1848 ec.Emit (OpCodes.Newobj, m);
1852 if (Value <= long.MaxValue && Value >= long.MinValue) {
1853 m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc);
1858 ec.EmitLong ((long) Value);
1859 ec.Emit (OpCodes.Newobj, m);
1864 ec.EmitInt (words [0]);
1865 ec.EmitInt (words [1]);
1866 ec.EmitInt (words [2]);
1869 ec.EmitInt (words [3] >> 31);
1874 m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc);
1876 ec.Emit (OpCodes.Newobj, m);
1880 public override bool IsDefaultValue {
1886 public override bool IsNegative {
1892 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1894 switch (target_type.BuiltinType) {
1895 case BuiltinTypeSpec.Type.SByte:
1896 return new SByteConstant (target_type, (sbyte) Value, loc);
1897 case BuiltinTypeSpec.Type.Byte:
1898 return new ByteConstant (target_type, (byte) Value, loc);
1899 case BuiltinTypeSpec.Type.Short:
1900 return new ShortConstant (target_type, (short) Value, loc);
1901 case BuiltinTypeSpec.Type.UShort:
1902 return new UShortConstant (target_type, (ushort) Value, loc);
1903 case BuiltinTypeSpec.Type.Int:
1904 return new IntConstant (target_type, (int) Value, loc);
1905 case BuiltinTypeSpec.Type.UInt:
1906 return new UIntConstant (target_type, (uint) Value, loc);
1907 case BuiltinTypeSpec.Type.Long:
1908 return new LongConstant (target_type, (long) Value, loc);
1909 case BuiltinTypeSpec.Type.ULong:
1910 return new ULongConstant (target_type, (ulong) Value, loc);
1911 case BuiltinTypeSpec.Type.Char:
1912 return new CharConstant (target_type, (char) Value, loc);
1913 case BuiltinTypeSpec.Type.Float:
1914 return new FloatConstant (target_type, (float) Value, loc);
1915 case BuiltinTypeSpec.Type.Double:
1916 return new DoubleConstant (target_type, (double) Value, loc);
1922 public override object GetValue ()
1927 public override string GetValueAsLiteral ()
1929 return Value.ToString () + "M";
1932 public override long GetValueAsLong ()
1934 throw new NotSupportedException ();
1938 public class StringConstant : Constant {
1939 public readonly string Value;
1941 public StringConstant (BuiltinTypes types, string s, Location loc)
1942 : this (types.String, s, loc)
1946 public StringConstant (TypeSpec type, string s, Location loc)
1950 eclass = ExprClass.Value;
1955 public override object GetValue ()
1960 public override string GetValueAsLiteral ()
1962 // FIXME: Escape the string.
1963 return "\"" + Value + "\"";
1966 public override long GetValueAsLong ()
1968 throw new NotSupportedException ();
1971 public override void Emit (EmitContext ec)
1973 if (Value == null) {
1979 // Use string.Empty for both literals and constants even if
1980 // it's not allowed at language level
1982 if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) {
1983 var string_type = ec.BuiltinTypes.String;
1984 if (ec.CurrentType != string_type) {
1985 var m = ec.Module.PredefinedMembers.StringEmpty.Get ();
1987 ec.Emit (OpCodes.Ldsfld, m);
1993 ec.Emit (OpCodes.Ldstr, Value);
1996 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1999 if (type != targetType)
2005 public override bool IsDefaultValue {
2007 return Value == null;
2011 public override bool IsNegative {
2017 public override bool IsNull {
2019 return IsDefaultValue;
2023 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2030 // Null constant can have its own type, think of `default (Foo)'
2032 public class NullConstant : Constant
2034 public NullConstant (TypeSpec type, Location loc)
2037 eclass = ExprClass.Value;
2041 public override Expression CreateExpressionTree (ResolveContext ec)
2043 if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2044 // Optimized version, also avoids referencing literal internal type
2045 Arguments args = new Arguments (1);
2046 args.Add (new Argument (this));
2047 return CreateExpressionFactoryCall (ec, "Constant", args);
2050 return base.CreateExpressionTree (ec);
2053 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
2055 switch (targetType.BuiltinType) {
2056 case BuiltinTypeSpec.Type.Object:
2057 // Type it as string cast
2058 enc.Encode (rc.Module.Compiler.BuiltinTypes.String);
2059 goto case BuiltinTypeSpec.Type.String;
2060 case BuiltinTypeSpec.Type.String:
2061 case BuiltinTypeSpec.Type.Type:
2062 enc.Encode (byte.MaxValue);
2065 var ac = targetType as ArrayContainer;
2066 if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) {
2067 enc.Encode (uint.MaxValue);
2074 base.EncodeAttributeValue (rc, enc, targetType);
2077 public override void Emit (EmitContext ec)
2081 // Only to make verifier happy
2082 if (type.IsGenericParameter)
2083 ec.Emit (OpCodes.Unbox_Any, type);
2086 public override string ExprClassName {
2088 return GetSignatureForError ();
2092 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2094 if (targetType.IsPointer) {
2095 if (IsLiteral || this is NullPointer)
2096 return new NullPointer (targetType, loc);
2101 // Exlude internal compiler types
2102 if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic)
2105 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2108 if (TypeSpec.IsReferenceType (targetType))
2109 return new NullConstant (targetType, loc);
2111 if (targetType.IsNullableType)
2112 return Nullable.LiftedNull.Create (targetType, loc);
2117 public override Constant ConvertImplicitly (TypeSpec targetType)
2119 return ConvertExplicitly (false, targetType);
2122 public override string GetSignatureForError ()
2127 public override object GetValue ()
2132 public override string GetValueAsLiteral ()
2134 return GetSignatureForError ();
2137 public override long GetValueAsLong ()
2139 throw new NotSupportedException ();
2142 public override bool IsDefaultValue {
2143 get { return true; }
2146 public override bool IsNegative {
2147 get { return false; }
2150 public override bool IsNull {
2151 get { return true; }
2154 public override bool IsZeroInteger {
2155 get { return true; }
2161 // A null constant in a pointer context
2163 class NullPointer : NullConstant
2165 public NullPointer (TypeSpec type, Location loc)
2170 public override Expression CreateExpressionTree (ResolveContext ec)
2172 Error_PointerInsideExpressionTree (ec);
2173 return base.CreateExpressionTree (ec);
2176 public override void Emit (EmitContext ec)
2179 // Emits null pointer
2182 ec.Emit (OpCodes.Conv_U);
2187 /// The value is constant, but when emitted has a side effect. This is
2188 /// used by BitwiseAnd to ensure that the second expression is invoked
2189 /// regardless of the value of the left side.
2191 public class SideEffectConstant : Constant
2193 public readonly Constant value;
2194 Expression side_effect;
2196 public SideEffectConstant (Constant value, Expression side_effect, Location loc)
2201 eclass = ExprClass.Value;
2203 while (side_effect is SideEffectConstant)
2204 side_effect = ((SideEffectConstant) side_effect).side_effect;
2205 this.side_effect = side_effect;
2208 public override bool IsSideEffectFree {
2214 public override object GetValue ()
2216 return value.GetValue ();
2219 public override string GetValueAsLiteral ()
2221 return value.GetValueAsLiteral ();
2224 public override long GetValueAsLong ()
2226 return value.GetValueAsLong ();
2229 public override void Emit (EmitContext ec)
2231 side_effect.EmitSideEffect (ec);
2235 public override void EmitSideEffect (EmitContext ec)
2237 side_effect.EmitSideEffect (ec);
2238 value.EmitSideEffect (ec);
2241 public override bool IsDefaultValue {
2242 get { return value.IsDefaultValue; }
2245 public override bool IsNegative {
2246 get { return value.IsNegative; }
2249 public override bool IsZeroInteger {
2250 get { return value.IsZeroInteger; }
2253 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2255 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2256 if (new_value == null)
2259 var c = new SideEffectConstant (new_value, side_effect, new_value.Location);
2260 c.type = target_type;