2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
13 using System.Globalization;
16 using IKVM.Reflection.Emit;
18 using System.Reflection.Emit;
21 namespace Mono.CSharp {
24 /// Base class for constants and literals.
26 public abstract class Constant : Expression
28 static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
30 protected Constant (Location loc)
35 override public string ToString ()
37 return this.GetType ().Name + " (" + GetValueAsLiteral () + ")";
41 /// This is used to obtain the actual value of the literal
42 /// cast into an object.
44 public abstract object GetValue ();
46 public abstract long GetValueAsLong ();
48 public abstract string GetValueAsLiteral ();
52 // Returns an object value which is typed to contant type
54 public virtual object GetTypedValue ()
60 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
62 if (!expl && IsLiteral &&
63 BuildinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
64 BuildinTypeSpec.IsPrimitiveTypeOrDecimal (type)) {
65 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
66 GetValueAsLiteral (), TypeManager.CSharpName (target));
68 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
72 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
74 Constant c = ConvertImplicitly (ec, type);
76 Error_ValueCannotBeConverted (ec, loc, type, false);
81 public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
83 if (this.type == type)
86 if (Convert.ImplicitNumericConversion (this, type) == null)
90 object constant_value = ChangeType (GetValue (), type, out fail);
93 // We should always catch the error before this is ever
94 // reached, by calling Convert.ImplicitStandardConversionExists
96 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
97 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
100 return CreateConstant (rc, type, constant_value, loc);
104 // Returns a constant instance based on Type
106 public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc)
108 return CreateConstantFromValue (t, v, loc).Resolve (rc);
111 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
113 if (t.BuildinType > 0) {
114 switch (t.BuildinType) {
115 case BuildinTypeSpec.Type.Int:
116 return new IntConstant ((int) v, loc);
117 case BuildinTypeSpec.Type.String:
118 return new StringConstant ((string) v, loc);
119 case BuildinTypeSpec.Type.UInt:
120 return new UIntConstant ((uint) v, loc);
121 case BuildinTypeSpec.Type.Long:
122 return new LongConstant ((long) v, loc);
123 case BuildinTypeSpec.Type.ULong:
124 return new ULongConstant ((ulong) v, loc);
125 case BuildinTypeSpec.Type.Float:
126 return new FloatConstant ((float) v, loc);
127 case BuildinTypeSpec.Type.Double:
128 return new DoubleConstant ((double) v, loc);
129 case BuildinTypeSpec.Type.Short:
130 return new ShortConstant ((short) v, loc);
131 case BuildinTypeSpec.Type.UShort:
132 return new UShortConstant ((ushort) v, loc);
133 case BuildinTypeSpec.Type.SByte:
134 return new SByteConstant ((sbyte) v, loc);
135 case BuildinTypeSpec.Type.Byte:
136 return new ByteConstant ((byte) v, loc);
137 case BuildinTypeSpec.Type.Char:
138 return new CharConstant ((char) v, loc);
139 case BuildinTypeSpec.Type.Bool:
140 return new BoolConstant ((bool) v, loc);
141 case BuildinTypeSpec.Type.Decimal:
142 return new DecimalConstant ((decimal) v, loc);
147 var real_type = EnumSpec.GetUnderlyingType (t);
148 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
152 if (TypeManager.IsNullableType (t))
153 return Nullable.LiftedNull.Create (t, loc);
155 if (TypeManager.IsReferenceType (t))
156 return new NullConstant (t, loc);
159 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
160 v, TypeManager.CSharpName (t));
163 public override Expression CreateExpressionTree (ResolveContext ec)
165 Arguments args = new Arguments (2);
166 args.Add (new Argument (this));
167 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
169 return CreateExpressionFactoryCall (ec, "Constant", args);
173 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
174 /// It throws OverflowException
176 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
177 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
179 // This is a custom version of Convert.ChangeType() which works
180 // with the TypeBuilder defined types when compiling corlib.
181 static object ChangeType (object value, TypeSpec targetType, out bool error)
183 IConvertible convert_value = value as IConvertible;
185 if (convert_value == null) {
191 // We cannot rely on build-in type conversions as they are
192 // more limited than what C# supports.
193 // See char -> float/decimal/double conversion
197 switch (targetType.BuildinType) {
198 case BuildinTypeSpec.Type.Bool:
199 return convert_value.ToBoolean (nfi);
200 case BuildinTypeSpec.Type.Byte:
201 return convert_value.ToByte (nfi);
202 case BuildinTypeSpec.Type.Char:
203 return convert_value.ToChar (nfi);
204 case BuildinTypeSpec.Type.Short:
205 return convert_value.ToInt16 (nfi);
206 case BuildinTypeSpec.Type.Int:
207 return convert_value.ToInt32 (nfi);
208 case BuildinTypeSpec.Type.Long:
209 return convert_value.ToInt64 (nfi);
210 case BuildinTypeSpec.Type.SByte:
211 return convert_value.ToSByte (nfi);
212 case BuildinTypeSpec.Type.Decimal:
213 if (convert_value.GetType () == typeof (char))
214 return (decimal) convert_value.ToInt32 (nfi);
215 return convert_value.ToDecimal (nfi);
216 case BuildinTypeSpec.Type.Double:
217 if (convert_value.GetType () == typeof (char))
218 return (double) convert_value.ToInt32 (nfi);
219 return convert_value.ToDouble (nfi);
220 case BuildinTypeSpec.Type.Float:
221 if (convert_value.GetType () == typeof (char))
222 return (float) convert_value.ToInt32 (nfi);
223 return convert_value.ToSingle (nfi);
224 case BuildinTypeSpec.Type.String:
225 return convert_value.ToString (nfi);
226 case BuildinTypeSpec.Type.UShort:
227 return convert_value.ToUInt16 (nfi);
228 case BuildinTypeSpec.Type.UInt:
229 return convert_value.ToUInt32 (nfi);
230 case BuildinTypeSpec.Type.ULong:
231 return convert_value.ToUInt64 (nfi);
232 case BuildinTypeSpec.Type.Object:
243 /// Attempts to do a compile-time folding of a constant cast.
245 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
248 return TryReduce (ec, target_type);
250 catch (OverflowException) {
251 if (ec.ConstantCheckState && Type.BuildinType != BuildinTypeSpec.Type.Decimal) {
252 ec.Report.Error (221, loc,
253 "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
254 GetValueAsLiteral (), target_type.GetSignatureForError ());
256 Error_ValueCannotBeConverted (ec, loc, target_type, false);
259 return New.Constantify (target_type, loc).Resolve (ec);
263 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
265 if (Type == target_type)
269 if (TypeManager.IsEnumType (target_type)) {
270 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
274 return new EnumConstant (c, target_type).Resolve (ec);
277 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
285 /// Need to pass type as the constant can require a boxing
286 /// and in such case no optimization is possible
288 public bool IsDefaultInitializer (TypeSpec type)
291 return IsDefaultValue;
293 return this is NullLiteral;
296 public abstract bool IsDefaultValue {
300 public abstract bool IsNegative {
305 // When constant is declared as literal
307 public virtual bool IsLiteral {
308 get { return false; }
311 public virtual bool IsOneInteger {
312 get { return false; }
316 // Returns true iff 1) the stack type of this is one of Object,
317 // int32, int64 and 2) this == 0 or this == null.
319 public virtual bool IsZeroInteger {
320 get { return false; }
323 public override void EmitSideEffect (EmitContext ec)
328 public sealed override Expression Clone (CloneContext clonectx)
330 // No cloning is not needed for constants
334 protected override void CloneTo (CloneContext clonectx, Expression target)
336 throw new NotSupportedException ("should not be reached");
339 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
342 return base.MakeExpression (ctx);
344 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
348 public new Constant Resolve (ResolveContext rc)
350 if (eclass != ExprClass.Unresolved)
353 // Resolved constant has to be still a constant
354 Constant c = (Constant) DoResolve (rc);
358 if ((c.eclass & ExprClass.Value) == 0) {
359 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
364 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
370 public abstract class IntegralConstant : Constant
372 protected IntegralConstant (Location loc) :
377 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
380 ConvertExplicitly (true, target);
381 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
385 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
386 GetValue ().ToString (), TypeManager.CSharpName (target));
390 public override string GetValueAsLiteral ()
392 return GetValue ().ToString ();
395 public abstract Constant Increment ();
398 public class BoolConstant : Constant {
399 public readonly bool Value;
401 public BoolConstant (bool val, Location loc):
407 protected override Expression DoResolve (ResolveContext ec)
409 type = TypeManager.bool_type;
410 eclass = ExprClass.Value;
414 public override object GetValue ()
416 return (object) Value;
419 public override string GetValueAsLiteral ()
421 return Value ? "true" : "false";
424 public override long GetValueAsLong ()
426 return Value ? 1 : 0;
429 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
434 public override void Emit (EmitContext ec)
437 ec.Emit (OpCodes.Ldc_I4_1);
439 ec.Emit (OpCodes.Ldc_I4_0);
442 public override bool IsDefaultValue {
448 public override bool IsNegative {
454 public override bool IsZeroInteger {
455 get { return Value == false; }
458 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
465 public class ByteConstant : IntegralConstant
467 public readonly byte Value;
469 public ByteConstant (byte v, Location loc):
475 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
480 public override void Emit (EmitContext ec)
485 protected override Expression DoResolve (ResolveContext ec)
487 type = TypeManager.byte_type;
488 eclass = ExprClass.Value;
492 public override object GetValue ()
497 public override long GetValueAsLong ()
502 public override Constant Increment ()
504 return new ByteConstant (checked ((byte)(Value + 1)), loc);
507 public override bool IsDefaultValue {
513 public override bool IsOneInteger {
519 public override bool IsNegative {
525 public override bool IsZeroInteger {
526 get { return Value == 0; }
529 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
531 switch (target_type.BuildinType) {
532 case BuildinTypeSpec.Type.SByte:
533 if (in_checked_context){
534 if (Value > SByte.MaxValue)
535 throw new OverflowException ();
537 return new SByteConstant ((sbyte) Value, Location);
538 case BuildinTypeSpec.Type.Short:
539 return new ShortConstant ((short) Value, Location);
540 case BuildinTypeSpec.Type.UShort:
541 return new UShortConstant ((ushort) Value, Location);
542 case BuildinTypeSpec.Type.Int:
543 return new IntConstant ((int) Value, Location);
544 case BuildinTypeSpec.Type.UInt:
545 return new UIntConstant ((uint) Value, Location);
546 case BuildinTypeSpec.Type.Long:
547 return new LongConstant ((long) Value, Location);
548 case BuildinTypeSpec.Type.ULong:
549 return new ULongConstant ((ulong) Value, Location);
550 case BuildinTypeSpec.Type.Float:
551 return new FloatConstant ((float) Value, Location);
552 case BuildinTypeSpec.Type.Double:
553 return new DoubleConstant ((double) Value, Location);
554 case BuildinTypeSpec.Type.Char:
555 return new CharConstant ((char) Value, Location);
556 case BuildinTypeSpec.Type.Decimal:
557 return new DecimalConstant ((decimal) Value, Location);
565 public class CharConstant : Constant {
566 public readonly char Value;
568 public CharConstant (char v, Location loc):
574 protected override Expression DoResolve (ResolveContext rc)
576 type = TypeManager.char_type;
577 eclass = ExprClass.Value;
581 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
583 enc.Encode ((ushort) Value);
586 public override void Emit (EmitContext ec)
591 static string descape (char c)
617 return c.ToString ();
620 public override object GetValue ()
625 public override long GetValueAsLong ()
630 public override string GetValueAsLiteral ()
632 return "\"" + descape (Value) + "\"";
635 public override bool IsDefaultValue {
641 public override bool IsNegative {
647 public override bool IsZeroInteger {
648 get { return Value == '\0'; }
651 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
653 switch (target_type.BuildinType) {
654 case BuildinTypeSpec.Type.Byte:
655 if (in_checked_context) {
656 if (Value < Byte.MinValue || Value > Byte.MaxValue)
657 throw new OverflowException ();
659 return new ByteConstant ((byte) Value, Location);
660 case BuildinTypeSpec.Type.SByte:
661 if (in_checked_context) {
662 if (Value > SByte.MaxValue)
663 throw new OverflowException ();
665 return new SByteConstant ((sbyte) Value, Location);
667 case BuildinTypeSpec.Type.Short:
668 if (in_checked_context) {
669 if (Value > Int16.MaxValue)
670 throw new OverflowException ();
672 return new ShortConstant ((short) Value, Location);
673 case BuildinTypeSpec.Type.Int:
674 return new IntConstant ((int) Value, Location);
675 case BuildinTypeSpec.Type.UInt:
676 return new UIntConstant ((uint) Value, Location);
677 case BuildinTypeSpec.Type.Long:
678 return new LongConstant ((long) Value, Location);
679 case BuildinTypeSpec.Type.ULong:
680 return new ULongConstant ((ulong) Value, Location);
681 case BuildinTypeSpec.Type.Float:
682 return new FloatConstant ((float) Value, Location);
683 case BuildinTypeSpec.Type.Double:
684 return new DoubleConstant ((double) Value, Location);
685 case BuildinTypeSpec.Type.Decimal:
686 return new DecimalConstant ((decimal) Value, Location);
694 public class SByteConstant : IntegralConstant {
695 public readonly sbyte Value;
697 public SByteConstant (sbyte v, Location loc):
703 protected override Expression DoResolve (ResolveContext rc)
705 type = TypeManager.sbyte_type;
706 eclass = ExprClass.Value;
710 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
715 public override void Emit (EmitContext ec)
720 public override object GetValue ()
725 public override long GetValueAsLong ()
730 public override Constant Increment ()
732 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
735 public override bool IsDefaultValue {
741 public override bool IsNegative {
747 public override bool IsOneInteger {
753 public override bool IsZeroInteger {
754 get { return Value == 0; }
757 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
759 switch (target_type.BuildinType) {
760 case BuildinTypeSpec.Type.Byte:
761 if (in_checked_context && Value < 0)
762 throw new OverflowException ();
763 return new ByteConstant ((byte) Value, Location);
764 case BuildinTypeSpec.Type.Short:
765 return new ShortConstant ((short) Value, Location);
766 case BuildinTypeSpec.Type.UShort:
767 if (in_checked_context && Value < 0)
768 throw new OverflowException ();
769 return new UShortConstant ((ushort) Value, Location);
770 case BuildinTypeSpec.Type.Int:
771 return new IntConstant ((int) Value, Location);
772 case BuildinTypeSpec.Type.UInt:
773 if (in_checked_context && Value < 0)
774 throw new OverflowException ();
775 return new UIntConstant ((uint) Value, Location);
776 case BuildinTypeSpec.Type.Long:
777 return new LongConstant ((long) Value, Location);
778 case BuildinTypeSpec.Type.ULong:
779 if (in_checked_context && Value < 0)
780 throw new OverflowException ();
781 return new ULongConstant ((ulong) Value, Location);
782 case BuildinTypeSpec.Type.Float:
783 return new FloatConstant ((float) Value, Location);
784 case BuildinTypeSpec.Type.Double:
785 return new DoubleConstant ((double) Value, Location);
786 case BuildinTypeSpec.Type.Char:
787 if (in_checked_context && Value < 0)
788 throw new OverflowException ();
789 return new CharConstant ((char) Value, Location);
790 case BuildinTypeSpec.Type.Decimal:
791 return new DecimalConstant ((decimal) Value, Location);
799 public class ShortConstant : IntegralConstant {
800 public readonly short Value;
802 public ShortConstant (short v, Location loc):
808 protected override Expression DoResolve (ResolveContext rc)
810 type = TypeManager.short_type;
811 eclass = ExprClass.Value;
815 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
820 public override void Emit (EmitContext ec)
825 public override object GetValue ()
830 public override long GetValueAsLong ()
835 public override Constant Increment ()
837 return new ShortConstant (checked((short)(Value + 1)), loc);
840 public override bool IsDefaultValue {
846 public override bool IsZeroInteger {
847 get { return Value == 0; }
850 public override bool IsNegative {
856 public override bool IsOneInteger {
862 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
864 switch (target_type.BuildinType) {
865 case BuildinTypeSpec.Type.Byte:
866 if (in_checked_context) {
867 if (Value < Byte.MinValue || Value > Byte.MaxValue)
868 throw new OverflowException ();
870 return new ByteConstant ((byte) Value, Location);
871 case BuildinTypeSpec.Type.SByte:
872 if (in_checked_context) {
873 if (Value < SByte.MinValue || Value > SByte.MaxValue)
874 throw new OverflowException ();
876 return new SByteConstant ((sbyte) Value, Location);
877 case BuildinTypeSpec.Type.UShort:
878 if (in_checked_context && Value < 0)
879 throw new OverflowException ();
881 return new UShortConstant ((ushort) Value, Location);
882 case BuildinTypeSpec.Type.Int:
883 return new IntConstant ((int) Value, Location);
884 case BuildinTypeSpec.Type.UInt:
885 if (in_checked_context && Value < 0)
886 throw new OverflowException ();
887 return new UIntConstant ((uint) Value, Location);
888 case BuildinTypeSpec.Type.Long:
889 return new LongConstant ((long) Value, Location);
890 case BuildinTypeSpec.Type.ULong:
891 if (in_checked_context && Value < 0)
892 throw new OverflowException ();
893 return new ULongConstant ((ulong) Value, Location);
894 case BuildinTypeSpec.Type.Float:
895 return new FloatConstant ((float) Value, Location);
896 case BuildinTypeSpec.Type.Double:
897 return new DoubleConstant ((double) Value, Location);
898 case BuildinTypeSpec.Type.Char:
899 if (in_checked_context) {
900 if (Value < Char.MinValue)
901 throw new OverflowException ();
903 return new CharConstant ((char) Value, Location);
904 case BuildinTypeSpec.Type.Decimal:
905 return new DecimalConstant ((decimal) Value, Location);
913 public class UShortConstant : IntegralConstant
915 public readonly ushort Value;
917 public UShortConstant (ushort v, Location loc):
923 protected override Expression DoResolve (ResolveContext rc)
925 type = TypeManager.ushort_type;
926 eclass = ExprClass.Value;
930 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
935 public override void Emit (EmitContext ec)
940 public override object GetValue ()
945 public override long GetValueAsLong ()
950 public override Constant Increment ()
952 return new UShortConstant (checked((ushort)(Value + 1)), loc);
955 public override bool IsDefaultValue {
961 public override bool IsNegative {
967 public override bool IsOneInteger {
973 public override bool IsZeroInteger {
974 get { return Value == 0; }
977 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
979 switch (target_type.BuildinType) {
980 case BuildinTypeSpec.Type.Byte:
981 if (in_checked_context) {
982 if (Value > Byte.MaxValue)
983 throw new OverflowException ();
985 return new ByteConstant ((byte) Value, Location);
986 case BuildinTypeSpec.Type.SByte:
987 if (in_checked_context) {
988 if (Value > SByte.MaxValue)
989 throw new OverflowException ();
991 return new SByteConstant ((sbyte) Value, Location);
992 case BuildinTypeSpec.Type.Short:
993 if (in_checked_context) {
994 if (Value > Int16.MaxValue)
995 throw new OverflowException ();
997 return new ShortConstant ((short) Value, Location);
998 case BuildinTypeSpec.Type.Int:
999 return new IntConstant ((int) Value, Location);
1000 case BuildinTypeSpec.Type.UInt:
1001 return new UIntConstant ((uint) Value, Location);
1002 case BuildinTypeSpec.Type.Long:
1003 return new LongConstant ((long) Value, Location);
1004 case BuildinTypeSpec.Type.ULong:
1005 return new ULongConstant ((ulong) Value, Location);
1006 case BuildinTypeSpec.Type.Float:
1007 return new FloatConstant ((float) Value, Location);
1008 case BuildinTypeSpec.Type.Double:
1009 return new DoubleConstant ((double) Value, Location);
1010 case BuildinTypeSpec.Type.Char:
1011 if (in_checked_context) {
1012 if (Value > Char.MaxValue)
1013 throw new OverflowException ();
1015 return new CharConstant ((char) Value, Location);
1016 case BuildinTypeSpec.Type.Decimal:
1017 return new DecimalConstant ((decimal) Value, Location);
1024 public class IntConstant : IntegralConstant {
1025 public readonly int Value;
1027 public IntConstant (int v, Location loc):
1033 protected override Expression DoResolve (ResolveContext rc)
1035 type = TypeManager.int32_type;
1036 eclass = ExprClass.Value;
1040 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1045 public override void Emit (EmitContext ec)
1050 public override object GetValue ()
1055 public override long GetValueAsLong ()
1060 public override Constant Increment ()
1062 return new IntConstant (checked(Value + 1), loc);
1065 public override bool IsDefaultValue {
1071 public override bool IsNegative {
1077 public override bool IsOneInteger {
1083 public override bool IsZeroInteger {
1084 get { return Value == 0; }
1087 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1089 switch (target_type.BuildinType) {
1090 case BuildinTypeSpec.Type.Byte:
1091 if (in_checked_context) {
1092 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1093 throw new OverflowException ();
1095 return new ByteConstant ((byte) Value, Location);
1096 case BuildinTypeSpec.Type.SByte:
1097 if (in_checked_context) {
1098 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1099 throw new OverflowException ();
1101 return new SByteConstant ((sbyte) Value, Location);
1102 case BuildinTypeSpec.Type.Short:
1103 if (in_checked_context) {
1104 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1105 throw new OverflowException ();
1107 return new ShortConstant ((short) Value, Location);
1108 case BuildinTypeSpec.Type.UShort:
1109 if (in_checked_context) {
1110 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1111 throw new OverflowException ();
1113 return new UShortConstant ((ushort) Value, Location);
1114 case BuildinTypeSpec.Type.UInt:
1115 if (in_checked_context) {
1116 if (Value < UInt32.MinValue)
1117 throw new OverflowException ();
1119 return new UIntConstant ((uint) Value, Location);
1120 case BuildinTypeSpec.Type.Long:
1121 return new LongConstant ((long) Value, Location);
1122 case BuildinTypeSpec.Type.ULong:
1123 if (in_checked_context && Value < 0)
1124 throw new OverflowException ();
1125 return new ULongConstant ((ulong) Value, Location);
1126 case BuildinTypeSpec.Type.Float:
1127 return new FloatConstant ((float) Value, Location);
1128 case BuildinTypeSpec.Type.Double:
1129 return new DoubleConstant ((double) Value, Location);
1130 case BuildinTypeSpec.Type.Char:
1131 if (in_checked_context) {
1132 if (Value < Char.MinValue || Value > Char.MaxValue)
1133 throw new OverflowException ();
1135 return new CharConstant ((char) Value, Location);
1136 case BuildinTypeSpec.Type.Decimal:
1137 return new DecimalConstant ((decimal) Value, Location);
1143 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1145 if (this.type == type)
1148 Constant c = TryImplicitIntConversion (type);
1150 return c.Resolve (rc);
1152 return base.ConvertImplicitly (rc, type);
1156 /// Attempts to perform an implicit constant conversion of the IntConstant
1157 /// into a different data type using casts (See Implicit Constant
1158 /// Expression Conversions)
1160 Constant TryImplicitIntConversion (TypeSpec target_type)
1162 switch (target_type.BuildinType) {
1163 case BuildinTypeSpec.Type.SByte:
1164 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1165 return new SByteConstant ((sbyte) Value, loc);
1167 case BuildinTypeSpec.Type.Byte:
1168 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1169 return new ByteConstant ((byte) Value, loc);
1171 case BuildinTypeSpec.Type.Short:
1172 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1173 return new ShortConstant ((short) Value, loc);
1175 case BuildinTypeSpec.Type.UShort:
1176 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1177 return new UShortConstant ((ushort) Value, loc);
1179 case BuildinTypeSpec.Type.UInt:
1181 return new UIntConstant ((uint) Value, loc);
1183 case BuildinTypeSpec.Type.ULong:
1185 // we can optimize this case: a positive int32
1186 // always fits on a uint64. But we need an opcode
1190 return new ULongConstant ((ulong) Value, loc);
1192 case BuildinTypeSpec.Type.Double:
1193 return new DoubleConstant ((double) Value, loc);
1194 case BuildinTypeSpec.Type.Float:
1195 return new FloatConstant ((float) Value, loc);
1202 public class UIntConstant : IntegralConstant {
1203 public readonly uint Value;
1205 public UIntConstant (uint v, Location loc):
1211 protected override Expression DoResolve (ResolveContext rc)
1213 type = TypeManager.uint32_type;
1214 eclass = ExprClass.Value;
1218 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1223 public override void Emit (EmitContext ec)
1225 ec.EmitInt (unchecked ((int) Value));
1228 public override object GetValue ()
1233 public override long GetValueAsLong ()
1238 public override Constant Increment ()
1240 return new UIntConstant (checked(Value + 1), loc);
1243 public override bool IsDefaultValue {
1249 public override bool IsNegative {
1255 public override bool IsOneInteger {
1261 public override bool IsZeroInteger {
1262 get { return Value == 0; }
1265 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1267 switch (target_type.BuildinType) {
1268 case BuildinTypeSpec.Type.Byte:
1269 if (in_checked_context) {
1270 if (Value < 0 || Value > byte.MaxValue)
1271 throw new OverflowException ();
1273 return new ByteConstant ((byte) Value, Location);
1274 case BuildinTypeSpec.Type.SByte:
1275 if (in_checked_context) {
1276 if (Value > SByte.MaxValue)
1277 throw new OverflowException ();
1279 return new SByteConstant ((sbyte) Value, Location);
1280 case BuildinTypeSpec.Type.Short:
1281 if (in_checked_context) {
1282 if (Value > Int16.MaxValue)
1283 throw new OverflowException ();
1285 return new ShortConstant ((short) Value, Location);
1286 case BuildinTypeSpec.Type.UShort:
1287 if (in_checked_context) {
1288 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1289 throw new OverflowException ();
1291 return new UShortConstant ((ushort) Value, Location);
1292 case BuildinTypeSpec.Type.Int:
1293 if (in_checked_context) {
1294 if (Value > Int32.MaxValue)
1295 throw new OverflowException ();
1297 return new IntConstant ((int) Value, Location);
1298 case BuildinTypeSpec.Type.Long:
1299 return new LongConstant ((long) Value, Location);
1300 case BuildinTypeSpec.Type.ULong:
1301 return new ULongConstant ((ulong) Value, Location);
1302 case BuildinTypeSpec.Type.Float:
1303 return new FloatConstant ((float) Value, Location);
1304 case BuildinTypeSpec.Type.Double:
1305 return new DoubleConstant ((double) Value, Location);
1306 case BuildinTypeSpec.Type.Char:
1307 if (in_checked_context) {
1308 if (Value < Char.MinValue || Value > Char.MaxValue)
1309 throw new OverflowException ();
1311 return new CharConstant ((char) Value, Location);
1312 case BuildinTypeSpec.Type.Decimal:
1313 return new DecimalConstant ((decimal) Value, Location);
1321 public class LongConstant : IntegralConstant {
1322 public readonly long Value;
1324 public LongConstant (long v, Location loc):
1330 protected override Expression DoResolve (ResolveContext rc)
1332 type = TypeManager.int64_type;
1333 eclass = ExprClass.Value;
1337 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1342 public override void Emit (EmitContext ec)
1344 ec.EmitLong (Value);
1347 public override object GetValue ()
1352 public override long GetValueAsLong ()
1357 public override Constant Increment ()
1359 return new LongConstant (checked(Value + 1), loc);
1362 public override bool IsDefaultValue {
1368 public override bool IsNegative {
1374 public override bool IsOneInteger {
1380 public override bool IsZeroInteger {
1381 get { return Value == 0; }
1384 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1386 switch (target_type.BuildinType) {
1387 case BuildinTypeSpec.Type.Byte:
1388 if (in_checked_context) {
1389 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1390 throw new OverflowException ();
1392 return new ByteConstant ((byte) Value, Location);
1393 case BuildinTypeSpec.Type.SByte:
1394 if (in_checked_context) {
1395 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1396 throw new OverflowException ();
1398 return new SByteConstant ((sbyte) Value, Location);
1399 case BuildinTypeSpec.Type.Short:
1400 if (in_checked_context) {
1401 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1402 throw new OverflowException ();
1404 return new ShortConstant ((short) Value, Location);
1405 case BuildinTypeSpec.Type.UShort:
1406 if (in_checked_context) {
1407 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1408 throw new OverflowException ();
1410 return new UShortConstant ((ushort) Value, Location);
1411 case BuildinTypeSpec.Type.Int:
1412 if (in_checked_context) {
1413 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1414 throw new OverflowException ();
1416 return new IntConstant ((int) Value, Location);
1417 case BuildinTypeSpec.Type.UInt:
1418 if (in_checked_context) {
1419 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1420 throw new OverflowException ();
1422 return new UIntConstant ((uint) Value, Location);
1423 case BuildinTypeSpec.Type.ULong:
1424 if (in_checked_context && Value < 0)
1425 throw new OverflowException ();
1426 return new ULongConstant ((ulong) Value, Location);
1427 case BuildinTypeSpec.Type.Float:
1428 return new FloatConstant ((float) Value, Location);
1429 case BuildinTypeSpec.Type.Double:
1430 return new DoubleConstant ((double) Value, Location);
1431 case BuildinTypeSpec.Type.Char:
1432 if (in_checked_context) {
1433 if (Value < Char.MinValue || Value > Char.MaxValue)
1434 throw new OverflowException ();
1436 return new CharConstant ((char) Value, Location);
1437 case BuildinTypeSpec.Type.Decimal:
1438 return new DecimalConstant ((decimal) Value, Location);
1444 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1446 if (Value >= 0 && type.BuildinType == BuildinTypeSpec.Type.ULong) {
1447 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1450 return base.ConvertImplicitly (rc, type);
1454 public class ULongConstant : IntegralConstant {
1455 public readonly ulong Value;
1457 public ULongConstant (ulong v, Location loc):
1463 protected override Expression DoResolve (ResolveContext rc)
1465 type = TypeManager.uint64_type;
1466 eclass = ExprClass.Value;
1470 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1475 public override void Emit (EmitContext ec)
1477 ec.EmitLong (unchecked ((long) Value));
1480 public override object GetValue ()
1485 public override long GetValueAsLong ()
1487 return (long) Value;
1490 public override Constant Increment ()
1492 return new ULongConstant (checked(Value + 1), loc);
1495 public override bool IsDefaultValue {
1501 public override bool IsNegative {
1507 public override bool IsOneInteger {
1513 public override bool IsZeroInteger {
1514 get { return Value == 0; }
1517 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1519 switch (target_type.BuildinType) {
1520 case BuildinTypeSpec.Type.Byte:
1521 if (in_checked_context && Value > Byte.MaxValue)
1522 throw new OverflowException ();
1523 return new ByteConstant ((byte) Value, Location);
1524 case BuildinTypeSpec.Type.SByte:
1525 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1526 throw new OverflowException ();
1527 return new SByteConstant ((sbyte) Value, Location);
1528 case BuildinTypeSpec.Type.Short:
1529 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1530 throw new OverflowException ();
1531 return new ShortConstant ((short) Value, Location);
1532 case BuildinTypeSpec.Type.UShort:
1533 if (in_checked_context && Value > UInt16.MaxValue)
1534 throw new OverflowException ();
1535 return new UShortConstant ((ushort) Value, Location);
1536 case BuildinTypeSpec.Type.Int:
1537 if (in_checked_context && Value > UInt32.MaxValue)
1538 throw new OverflowException ();
1539 return new IntConstant ((int) Value, Location);
1540 case BuildinTypeSpec.Type.UInt:
1541 if (in_checked_context && Value > UInt32.MaxValue)
1542 throw new OverflowException ();
1543 return new UIntConstant ((uint) Value, Location);
1544 case BuildinTypeSpec.Type.Long:
1545 if (in_checked_context && Value > Int64.MaxValue)
1546 throw new OverflowException ();
1547 return new LongConstant ((long) Value, Location);
1548 case BuildinTypeSpec.Type.Float:
1549 return new FloatConstant ((float) Value, Location);
1550 case BuildinTypeSpec.Type.Double:
1551 return new DoubleConstant ((double) Value, Location);
1552 case BuildinTypeSpec.Type.Char:
1553 if (in_checked_context && Value > Char.MaxValue)
1554 throw new OverflowException ();
1555 return new CharConstant ((char) Value, Location);
1556 case BuildinTypeSpec.Type.Decimal:
1557 return new DecimalConstant ((decimal) Value, Location);
1565 public class FloatConstant : Constant {
1568 public FloatConstant (float v, Location loc):
1574 protected override Expression DoResolve (ResolveContext rc)
1576 type = TypeManager.float_type;
1577 eclass = ExprClass.Value;
1581 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1586 public override void Emit (EmitContext ec)
1588 ec.Emit (OpCodes.Ldc_R4, Value);
1591 public override object GetValue ()
1596 public override string GetValueAsLiteral ()
1598 return Value.ToString ();
1601 public override long GetValueAsLong ()
1603 throw new NotSupportedException ();
1606 public override bool IsDefaultValue {
1612 public override bool IsNegative {
1618 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1620 switch (target_type.BuildinType) {
1621 case BuildinTypeSpec.Type.Byte:
1622 if (in_checked_context) {
1623 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1624 throw new OverflowException ();
1626 return new ByteConstant ((byte) Value, Location);
1627 case BuildinTypeSpec.Type.SByte:
1628 if (in_checked_context) {
1629 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1630 throw new OverflowException ();
1632 return new SByteConstant ((sbyte) Value, Location);
1633 case BuildinTypeSpec.Type.Short:
1634 if (in_checked_context) {
1635 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1636 throw new OverflowException ();
1638 return new ShortConstant ((short) Value, Location);
1639 case BuildinTypeSpec.Type.UShort:
1640 if (in_checked_context) {
1641 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1642 throw new OverflowException ();
1644 return new UShortConstant ((ushort) Value, Location);
1645 case BuildinTypeSpec.Type.Int:
1646 if (in_checked_context) {
1647 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1648 throw new OverflowException ();
1650 return new IntConstant ((int) Value, Location);
1651 case BuildinTypeSpec.Type.UInt:
1652 if (in_checked_context) {
1653 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1654 throw new OverflowException ();
1656 return new UIntConstant ((uint) Value, Location);
1657 case BuildinTypeSpec.Type.Long:
1658 if (in_checked_context) {
1659 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1660 throw new OverflowException ();
1662 return new LongConstant ((long) Value, Location);
1663 case BuildinTypeSpec.Type.ULong:
1664 if (in_checked_context) {
1665 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1666 throw new OverflowException ();
1668 return new ULongConstant ((ulong) Value, Location);
1669 case BuildinTypeSpec.Type.Double:
1670 return new DoubleConstant ((double) Value, Location);
1671 case BuildinTypeSpec.Type.Char:
1672 if (in_checked_context) {
1673 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1674 throw new OverflowException ();
1676 return new CharConstant ((char) Value, Location);
1677 case BuildinTypeSpec.Type.Decimal:
1678 return new DecimalConstant ((decimal) Value, Location);
1686 public class DoubleConstant : Constant {
1687 public double Value;
1689 public DoubleConstant (double v, Location loc):
1695 protected override Expression DoResolve (ResolveContext rc)
1697 type = TypeManager.double_type;
1698 eclass = ExprClass.Value;
1702 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1707 public override void Emit (EmitContext ec)
1709 ec.Emit (OpCodes.Ldc_R8, Value);
1712 public override object GetValue ()
1717 public override string GetValueAsLiteral ()
1719 return Value.ToString ();
1722 public override long GetValueAsLong ()
1724 throw new NotSupportedException ();
1727 public override bool IsDefaultValue {
1733 public override bool IsNegative {
1739 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1741 switch (target_type.BuildinType) {
1742 case BuildinTypeSpec.Type.Byte:
1743 if (in_checked_context) {
1744 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1745 throw new OverflowException ();
1747 return new ByteConstant ((byte) Value, Location);
1748 case BuildinTypeSpec.Type.SByte:
1749 if (in_checked_context) {
1750 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1751 throw new OverflowException ();
1753 return new SByteConstant ((sbyte) Value, Location);
1754 case BuildinTypeSpec.Type.Short:
1755 if (in_checked_context) {
1756 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1757 throw new OverflowException ();
1759 return new ShortConstant ((short) Value, Location);
1760 case BuildinTypeSpec.Type.UShort:
1761 if (in_checked_context) {
1762 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1763 throw new OverflowException ();
1765 return new UShortConstant ((ushort) Value, Location);
1766 case BuildinTypeSpec.Type.Int:
1767 if (in_checked_context) {
1768 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1769 throw new OverflowException ();
1771 return new IntConstant ((int) Value, Location);
1772 case BuildinTypeSpec.Type.UInt:
1773 if (in_checked_context) {
1774 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1775 throw new OverflowException ();
1777 return new UIntConstant ((uint) Value, Location);
1778 case BuildinTypeSpec.Type.Long:
1779 if (in_checked_context) {
1780 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1781 throw new OverflowException ();
1783 return new LongConstant ((long) Value, Location);
1784 case BuildinTypeSpec.Type.ULong:
1785 if (in_checked_context) {
1786 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1787 throw new OverflowException ();
1789 return new ULongConstant ((ulong) Value, Location);
1790 case BuildinTypeSpec.Type.Float:
1791 return new FloatConstant ((float) Value, Location);
1792 case BuildinTypeSpec.Type.Char:
1793 if (in_checked_context) {
1794 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1795 throw new OverflowException ();
1797 return new CharConstant ((char) Value, Location);
1798 case BuildinTypeSpec.Type.Decimal:
1799 return new DecimalConstant ((decimal) Value, Location);
1807 public class DecimalConstant : Constant {
1808 public readonly decimal Value;
1810 public DecimalConstant (decimal d, Location loc):
1816 protected override Expression DoResolve (ResolveContext rc)
1818 type = TypeManager.decimal_type;
1819 eclass = ExprClass.Value;
1823 public override void Emit (EmitContext ec)
1825 int [] words = decimal.GetBits (Value);
1826 int power = (words [3] >> 16) & 0xff;
1829 if (Value <= int.MaxValue && Value >= int.MinValue) {
1830 if (TypeManager.void_decimal_ctor_int_arg == null) {
1831 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1832 TypeManager.decimal_type, loc, TypeManager.int32_type);
1834 if (TypeManager.void_decimal_ctor_int_arg == null)
1838 ec.EmitInt ((int) Value);
1839 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1843 if (Value <= long.MaxValue && Value >= long.MinValue) {
1844 if (TypeManager.void_decimal_ctor_long_arg == null) {
1845 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1846 TypeManager.decimal_type, loc, TypeManager.int64_type);
1848 if (TypeManager.void_decimal_ctor_long_arg == null)
1852 ec.EmitLong ((long) Value);
1853 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1858 ec.EmitInt (words [0]);
1859 ec.EmitInt (words [1]);
1860 ec.EmitInt (words [2]);
1863 ec.EmitInt (words [3] >> 31);
1868 if (TypeManager.void_decimal_ctor_five_args == null) {
1869 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1870 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1871 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1873 if (TypeManager.void_decimal_ctor_five_args == null)
1877 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
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.BuildinType) {
1895 case BuildinTypeSpec.Type.SByte:
1896 return new SByteConstant ((sbyte) Value, loc);
1897 case BuildinTypeSpec.Type.Byte:
1898 return new ByteConstant ((byte) Value, loc);
1899 case BuildinTypeSpec.Type.Short:
1900 return new ShortConstant ((short) Value, loc);
1901 case BuildinTypeSpec.Type.UShort:
1902 return new UShortConstant ((ushort) Value, loc);
1903 case BuildinTypeSpec.Type.Int:
1904 return new IntConstant ((int) Value, loc);
1905 case BuildinTypeSpec.Type.UInt:
1906 return new UIntConstant ((uint) Value, loc);
1907 case BuildinTypeSpec.Type.Long:
1908 return new LongConstant ((long) Value, loc);
1909 case BuildinTypeSpec.Type.ULong:
1910 return new ULongConstant ((ulong) Value, loc);
1911 case BuildinTypeSpec.Type.Char:
1912 return new CharConstant ((char) Value, loc);
1913 case BuildinTypeSpec.Type.Float:
1914 return new FloatConstant ((float) Value, loc);
1915 case BuildinTypeSpec.Type.Double:
1916 return new DoubleConstant ((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 (string s, Location loc):
1947 protected override Expression DoResolve (ResolveContext rc)
1949 type = TypeManager.string_type;
1950 eclass = ExprClass.Value;
1954 public override object GetValue ()
1959 public override string GetValueAsLiteral ()
1961 // FIXME: Escape the string.
1962 return "\"" + Value + "\"";
1965 public override long GetValueAsLong ()
1967 throw new NotSupportedException ();
1970 public override void Emit (EmitContext ec)
1972 if (Value == null) {
1973 ec.Emit (OpCodes.Ldnull);
1978 // Use string.Empty for both literals and constants even if
1979 // it's not allowed at language level
1981 if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize && ec.CurrentType != TypeManager.string_type) {
1982 if (TypeManager.string_empty == null)
1983 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type);
1985 if (TypeManager.string_empty != null) {
1986 ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1991 ec.Emit (OpCodes.Ldstr, Value);
1994 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1997 if (type != targetType)
2003 public override bool IsDefaultValue {
2005 return Value == null;
2009 public override bool IsNegative {
2015 public override bool IsNull {
2017 return IsDefaultValue;
2021 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2028 // Null constant can have its own type, think of `default (Foo)'
2030 public class NullConstant : Constant
2032 public NullConstant (TypeSpec type, Location loc)
2035 eclass = ExprClass.Value;
2039 public override Expression CreateExpressionTree (ResolveContext ec)
2041 if (type == InternalType.Null || type == TypeManager.object_type) {
2042 // Optimized version, also avoids referencing literal internal type
2043 Arguments args = new Arguments (1);
2044 args.Add (new Argument (this));
2045 return CreateExpressionFactoryCall (ec, "Constant", args);
2048 return base.CreateExpressionTree (ec);
2051 protected override Expression DoResolve (ResolveContext ec)
2056 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
2058 // Type it as string cast
2059 if (targetType.BuildinType == BuildinTypeSpec.Type.Object || targetType == InternalType.Null)
2060 enc.Encode (TypeManager.string_type);
2062 var ac = targetType as ArrayContainer;
2064 if (ac.Rank != 1 || ac.Element.IsArray)
2065 base.EncodeAttributeValue (rc, enc, targetType);
2067 enc.Encode (uint.MaxValue);
2069 enc.Encode (byte.MaxValue);
2073 public override void Emit (EmitContext ec)
2075 ec.Emit (OpCodes.Ldnull);
2077 // Only to make verifier happy
2078 if (TypeManager.IsGenericParameter (type))
2079 ec.Emit (OpCodes.Unbox_Any, type);
2082 public override string ExprClassName {
2084 return GetSignatureForError ();
2088 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2090 if (targetType.IsPointer) {
2091 if (IsLiteral || this is NullPointer)
2092 return new EmptyConstantCast (new NullPointer (loc), targetType);
2097 // Exlude internal compiler types
2098 if (targetType.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null)
2101 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2104 if (TypeManager.IsReferenceType (targetType))
2105 return new NullConstant (targetType, loc);
2107 if (TypeManager.IsNullableType (targetType))
2108 return Nullable.LiftedNull.Create (targetType, loc);
2113 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
2115 return ConvertExplicitly (false, targetType);
2118 public override string GetSignatureForError ()
2123 public override object GetValue ()
2128 public override string GetValueAsLiteral ()
2130 return GetSignatureForError ();
2133 public override long GetValueAsLong ()
2135 throw new NotSupportedException ();
2138 public override bool IsDefaultValue {
2139 get { return true; }
2142 public override bool IsNegative {
2143 get { return false; }
2146 public override bool IsNull {
2147 get { return true; }
2150 public override bool IsZeroInteger {
2151 get { return true; }
2156 /// The value is constant, but when emitted has a side effect. This is
2157 /// used by BitwiseAnd to ensure that the second expression is invoked
2158 /// regardless of the value of the left side.
2160 public class SideEffectConstant : Constant {
2161 public Constant value;
2162 Expression side_effect;
2164 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2167 while (side_effect is SideEffectConstant)
2168 side_effect = ((SideEffectConstant) side_effect).side_effect;
2169 this.side_effect = side_effect;
2172 protected override Expression DoResolve (ResolveContext rc)
2174 value = value.Resolve (rc);
2177 eclass = ExprClass.Value;
2181 public override object GetValue ()
2183 return value.GetValue ();
2186 public override string GetValueAsLiteral ()
2188 return value.GetValueAsLiteral ();
2191 public override long GetValueAsLong ()
2193 return value.GetValueAsLong ();
2196 public override void Emit (EmitContext ec)
2198 side_effect.EmitSideEffect (ec);
2202 public override void EmitSideEffect (EmitContext ec)
2204 side_effect.EmitSideEffect (ec);
2205 value.EmitSideEffect (ec);
2208 public override bool IsDefaultValue {
2209 get { return value.IsDefaultValue; }
2212 public override bool IsNegative {
2213 get { return value.IsNegative; }
2216 public override bool IsZeroInteger {
2217 get { return value.IsZeroInteger; }
2220 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2222 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2223 if (new_value == null)
2226 var c = new SideEffectConstant (new_value, side_effect, new_value.Location);
2227 c.type = target_type;