[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / mcs / constant.cs
blobc16a0aa1c970df6a48d579c56ce5f32731e29ba6
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
7 //
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
10 // Copyright 2011-2013 Xamarin Inc
13 using System;
14 using System.Globalization;
16 #if STATIC
17 using IKVM.Reflection.Emit;
18 #else
19 using System.Reflection.Emit;
20 #endif
22 namespace Mono.CSharp {
24 /// <summary>
25 /// Base class for constants and literals.
26 /// </summary>
27 public abstract class Constant : Expression
29 static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
31 protected Constant (Location loc)
33 this.loc = loc;
36 override public string ToString ()
38 return this.GetType ().Name + " (" + GetValueAsLiteral () + ")";
41 /// <summary>
42 /// This is used to obtain the actual value of the literal
43 /// cast into an object.
44 /// </summary>
45 public abstract object GetValue ();
47 public abstract long GetValueAsLong ();
49 public abstract string GetValueAsLiteral ();
51 #if !STATIC
53 // Returns an object value which is typed to contant type
55 public virtual object GetTypedValue ()
57 return GetValue ();
59 #endif
61 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
63 if (!expl && IsLiteral && type.BuiltinType != BuiltinTypeSpec.Type.Double &&
64 BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
65 BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) {
66 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
67 GetValueAsLiteral (), target.GetSignatureForError ());
68 } else {
69 base.Error_ValueCannotBeConverted (ec, target, expl);
73 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type)
75 Constant c = ConvertImplicitly (type);
76 if (c == null)
77 Error_ValueCannotBeConverted (ec, type, false);
79 return c;
82 public override bool ContainsEmitWithAwait ()
84 return false;
87 public virtual Constant ConvertImplicitly (TypeSpec type)
89 if (this.type == type)
90 return this;
92 if (!Convert.ImplicitNumericConversionExists (this.type, type))
93 return null;
95 bool fail;
96 object constant_value = ChangeType (GetValue (), type, out fail);
97 if (fail){
99 // We should always catch the error before this is ever
100 // reached, by calling Convert.ImplicitStandardConversionExists
102 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
103 Type.GetSignatureForError (), type.GetSignatureForError ());
106 return CreateConstantFromValue (type, constant_value, loc);
110 // Returns a constant instance based on Type
112 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
114 switch (t.BuiltinType) {
115 case BuiltinTypeSpec.Type.Int:
116 return new IntConstant (t, (int) v, loc);
117 case BuiltinTypeSpec.Type.String:
118 return new StringConstant (t, (string) v, loc);
119 case BuiltinTypeSpec.Type.UInt:
120 return new UIntConstant (t, (uint) v, loc);
121 case BuiltinTypeSpec.Type.Long:
122 return new LongConstant (t, (long) v, loc);
123 case BuiltinTypeSpec.Type.ULong:
124 return new ULongConstant (t, (ulong) v, loc);
125 case BuiltinTypeSpec.Type.Float:
126 return new FloatConstant (t, (float) v, loc);
127 case BuiltinTypeSpec.Type.Double:
128 return new DoubleConstant (t, (double) v, loc);
129 case BuiltinTypeSpec.Type.Short:
130 return new ShortConstant (t, (short) v, loc);
131 case BuiltinTypeSpec.Type.UShort:
132 return new UShortConstant (t, (ushort) v, loc);
133 case BuiltinTypeSpec.Type.SByte:
134 return new SByteConstant (t, (sbyte) v, loc);
135 case BuiltinTypeSpec.Type.Byte:
136 return new ByteConstant (t, (byte) v, loc);
137 case BuiltinTypeSpec.Type.Char:
138 return new CharConstant (t, (char) v, loc);
139 case BuiltinTypeSpec.Type.Bool:
140 return new BoolConstant (t, (bool) v, loc);
141 case BuiltinTypeSpec.Type.Decimal:
142 return new DecimalConstant (t, (decimal) v, loc);
145 if (t.IsEnum) {
146 var real_type = EnumSpec.GetUnderlyingType (t);
147 return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t);
150 if (v == null) {
151 if (t.IsNullableType)
152 return Nullable.LiftedNull.Create (t, loc);
154 if (TypeSpec.IsReferenceType (t))
155 return new NullConstant (t, loc);
158 #if STATIC
159 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ());
160 #else
161 return null;
162 #endif
166 // Returns a constant instance based on value and type. This is probing version of
167 // CreateConstantFromValue
169 public static Constant ExtractConstantFromValue (TypeSpec t, object v, Location loc)
171 switch (t.BuiltinType) {
172 case BuiltinTypeSpec.Type.Int:
173 if (v is int)
174 return new IntConstant (t, (int) v, loc);
175 break;
176 case BuiltinTypeSpec.Type.String:
177 if (v is string)
178 return new StringConstant (t, (string) v, loc);
179 break;
180 case BuiltinTypeSpec.Type.UInt:
181 if (v is uint)
182 return new UIntConstant (t, (uint) v, loc);
183 break;
184 case BuiltinTypeSpec.Type.Long:
185 if (v is long)
186 return new LongConstant (t, (long) v, loc);
187 break;
188 case BuiltinTypeSpec.Type.ULong:
189 if (v is ulong)
190 return new ULongConstant (t, (ulong) v, loc);
191 break;
192 case BuiltinTypeSpec.Type.Float:
193 if (v is float)
194 return new FloatConstant (t, (float) v, loc);
195 break;
196 case BuiltinTypeSpec.Type.Double:
197 if (v is double)
198 return new DoubleConstant (t, (double) v, loc);
199 break;
200 case BuiltinTypeSpec.Type.Short:
201 if (v is short)
202 return new ShortConstant (t, (short) v, loc);
203 break;
204 case BuiltinTypeSpec.Type.UShort:
205 if (v is ushort)
206 return new UShortConstant (t, (ushort) v, loc);
207 break;
208 case BuiltinTypeSpec.Type.SByte:
209 if (v is sbyte)
210 return new SByteConstant (t, (sbyte) v, loc);
211 break;
212 case BuiltinTypeSpec.Type.Byte:
213 if (v is byte)
214 return new ByteConstant (t, (byte) v, loc);
215 break;
216 case BuiltinTypeSpec.Type.Char:
217 if (v is char)
218 return new CharConstant (t, (char) v, loc);
219 break;
220 case BuiltinTypeSpec.Type.Bool:
221 if (v is bool)
222 return new BoolConstant (t, (bool) v, loc);
223 break;
224 case BuiltinTypeSpec.Type.Decimal:
225 if (v is decimal)
226 return new DecimalConstant (t, (decimal) v, loc);
227 break;
230 if (t.IsEnum) {
231 var real_type = EnumSpec.GetUnderlyingType (t);
232 return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t);
235 if (v == null) {
236 if (t.IsNullableType)
237 return Nullable.LiftedNull.Create (t, loc);
239 if (TypeSpec.IsReferenceType (t))
240 return new NullConstant (t, loc);
243 return null;
247 public override Expression CreateExpressionTree (ResolveContext ec)
249 Arguments args = new Arguments (2);
250 args.Add (new Argument (this));
251 args.Add (new Argument (new TypeOf (type, loc)));
253 return CreateExpressionFactoryCall (ec, "Constant", args);
256 /// <summary>
257 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
258 /// It throws OverflowException
259 /// </summary>
260 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
261 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
263 // This is a custom version of Convert.ChangeType() which works
264 // with the TypeBuilder defined types when compiling corlib.
265 static object ChangeType (object value, TypeSpec targetType, out bool error)
267 IConvertible convert_value = value as IConvertible;
269 if (convert_value == null) {
270 error = true;
271 return null;
275 // We cannot rely on build-in type conversions as they are
276 // more limited than what C# supports.
277 // See char -> float/decimal/double conversion
279 error = false;
280 try {
281 switch (targetType.BuiltinType) {
282 case BuiltinTypeSpec.Type.Bool:
283 return convert_value.ToBoolean (nfi);
284 case BuiltinTypeSpec.Type.Byte:
285 return convert_value.ToByte (nfi);
286 case BuiltinTypeSpec.Type.Char:
287 return convert_value.ToChar (nfi);
288 case BuiltinTypeSpec.Type.Short:
289 return convert_value.ToInt16 (nfi);
290 case BuiltinTypeSpec.Type.Int:
291 return convert_value.ToInt32 (nfi);
292 case BuiltinTypeSpec.Type.Long:
293 return convert_value.ToInt64 (nfi);
294 case BuiltinTypeSpec.Type.SByte:
295 return convert_value.ToSByte (nfi);
296 case BuiltinTypeSpec.Type.Decimal:
297 if (convert_value.GetType () == typeof (char))
298 return (decimal) convert_value.ToInt32 (nfi);
299 return convert_value.ToDecimal (nfi);
300 case BuiltinTypeSpec.Type.Double:
301 if (convert_value.GetType () == typeof (char))
302 return (double) convert_value.ToInt32 (nfi);
303 return convert_value.ToDouble (nfi);
304 case BuiltinTypeSpec.Type.Float:
305 if (convert_value.GetType () == typeof (char))
306 return (float) convert_value.ToInt32 (nfi);
307 return convert_value.ToSingle (nfi);
308 case BuiltinTypeSpec.Type.String:
309 return convert_value.ToString (nfi);
310 case BuiltinTypeSpec.Type.UShort:
311 return convert_value.ToUInt16 (nfi);
312 case BuiltinTypeSpec.Type.UInt:
313 return convert_value.ToUInt32 (nfi);
314 case BuiltinTypeSpec.Type.ULong:
315 return convert_value.ToUInt64 (nfi);
316 case BuiltinTypeSpec.Type.Object:
317 return value;
319 } catch {
322 error = true;
323 return null;
326 protected override Expression DoResolve (ResolveContext rc)
328 return this;
332 // Attempts to do a compile-time folding of a constant cast and handles
333 // error reporting for constant overlows only, on normal conversion
334 // errors returns null
336 public Constant Reduce (ResolveContext ec, TypeSpec target_type)
338 try {
339 return TryReduceConstant (ec, target_type);
340 } catch (OverflowException) {
341 if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
342 ec.Report.Error (221, loc,
343 "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
344 GetValueAsLiteral (), target_type.GetSignatureForError ());
345 } else {
346 Error_ValueCannotBeConverted (ec, target_type, false);
349 return New.Constantify (target_type, loc);
353 public Constant TryReduce (ResolveContext rc, TypeSpec targetType)
355 try {
356 return TryReduceConstant (rc, targetType);
357 } catch (OverflowException) {
358 return null;
362 Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type)
364 if (Type == target_type) {
366 // Reducing literal value produces a new constant. Syntactically 10 is not same as (int)10
368 if (IsLiteral)
369 return CreateConstantFromValue (target_type, GetValue (), loc);
371 return this;
374 Constant c;
375 if (target_type.IsEnum) {
376 c = TryReduceConstant (ec, EnumSpec.GetUnderlyingType (target_type));
377 if (c == null)
378 return null;
380 return new EnumConstant (c, target_type);
383 return ConvertExplicitly (ec.ConstantCheckState, target_type);
386 /// <summary>
387 /// Need to pass type as the constant can require a boxing
388 /// and in such case no optimization is possible
389 /// </summary>
390 public bool IsDefaultInitializer (TypeSpec type)
392 if (type == Type)
393 return IsDefaultValue;
395 return this is NullLiteral;
398 public abstract bool IsDefaultValue {
399 get;
402 public abstract bool IsNegative {
403 get;
407 // When constant is declared as literal
409 public virtual bool IsLiteral {
410 get { return false; }
413 public virtual bool IsOneInteger {
414 get { return false; }
417 public override bool IsSideEffectFree {
418 get {
419 return true;
424 // Returns true iff 1) the stack type of this is one of Object,
425 // int32, int64 and 2) this == 0 or this == null.
427 public virtual bool IsZeroInteger {
428 get { return false; }
431 public override void EmitSideEffect (EmitContext ec)
433 // do nothing
436 public sealed override Expression Clone (CloneContext clonectx)
438 // No cloning is not needed for constants
439 return this;
442 protected override void CloneTo (CloneContext clonectx, Expression target)
444 throw new NotSupportedException ("should not be reached");
447 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
449 #if STATIC
450 return base.MakeExpression (ctx);
451 #else
452 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
453 #endif
456 public new bool Resolve (ResolveContext rc)
458 // It exists only as hint not to call Resolve on constants
459 return true;
463 public abstract class IntegralConstant : Constant
465 protected IntegralConstant (TypeSpec type, Location loc)
466 : base (loc)
468 this.type = type;
469 eclass = ExprClass.Value;
472 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
474 try {
475 ConvertExplicitly (true, target);
476 base.Error_ValueCannotBeConverted (ec, target, expl);
478 catch
480 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
481 GetValueAsLiteral (), target.GetSignatureForError ());
485 public override string GetValueAsLiteral ()
487 return GetValue ().ToString ();
490 public abstract Constant Increment ();
493 public class BoolConstant : Constant {
494 public readonly bool Value;
496 public BoolConstant (BuiltinTypes types, bool val, Location loc)
497 : this (types.Bool, val, loc)
501 public BoolConstant (TypeSpec type, bool val, Location loc)
502 : base (loc)
504 eclass = ExprClass.Value;
505 this.type = type;
507 Value = val;
510 public override object GetValue ()
512 return (object) Value;
515 public override string GetValueAsLiteral ()
517 return Value ? "true" : "false";
520 public override long GetValueAsLong ()
522 return Value ? 1 : 0;
525 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
527 enc.Encode (Value);
530 public override void Emit (EmitContext ec)
532 if (Value)
533 ec.EmitInt (1);
534 else
535 ec.EmitInt (0);
538 public override bool IsDefaultValue {
539 get {
540 return !Value;
544 public override bool IsNegative {
545 get {
546 return false;
550 public override bool IsZeroInteger {
551 get { return Value == false; }
554 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
556 return null;
561 public class ByteConstant : IntegralConstant
563 public readonly byte Value;
565 public ByteConstant (BuiltinTypes types, byte v, Location loc)
566 : this (types.Byte, v, loc)
570 public ByteConstant (TypeSpec type, byte v, Location loc)
571 : base (type, loc)
573 Value = v;
576 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
578 enc.Encode (Value);
581 public override void Emit (EmitContext ec)
583 ec.EmitInt (Value);
586 public override object GetValue ()
588 return Value;
591 public override long GetValueAsLong ()
593 return Value;
596 public override Constant Increment ()
598 return new ByteConstant (type, checked ((byte)(Value + 1)), loc);
601 public override bool IsDefaultValue {
602 get {
603 return Value == 0;
607 public override bool IsOneInteger {
608 get {
609 return Value == 1;
613 public override bool IsNegative {
614 get {
615 return false;
619 public override bool IsZeroInteger {
620 get { return Value == 0; }
623 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
625 switch (target_type.BuiltinType) {
626 case BuiltinTypeSpec.Type.SByte:
627 if (in_checked_context){
628 if (Value > SByte.MaxValue)
629 throw new OverflowException ();
631 return new SByteConstant (target_type, (sbyte) Value, Location);
632 case BuiltinTypeSpec.Type.Short:
633 return new ShortConstant (target_type, (short) Value, Location);
634 case BuiltinTypeSpec.Type.UShort:
635 return new UShortConstant (target_type, (ushort) Value, Location);
636 case BuiltinTypeSpec.Type.Int:
637 return new IntConstant (target_type, (int) Value, Location);
638 case BuiltinTypeSpec.Type.UInt:
639 return new UIntConstant (target_type, (uint) Value, Location);
640 case BuiltinTypeSpec.Type.Long:
641 return new LongConstant (target_type, (long) Value, Location);
642 case BuiltinTypeSpec.Type.ULong:
643 return new ULongConstant (target_type, (ulong) Value, Location);
644 case BuiltinTypeSpec.Type.Float:
645 return new FloatConstant (target_type, (float) Value, Location);
646 case BuiltinTypeSpec.Type.Double:
647 return new DoubleConstant (target_type, (double) Value, Location);
648 case BuiltinTypeSpec.Type.Char:
649 return new CharConstant (target_type, (char) Value, Location);
650 case BuiltinTypeSpec.Type.Decimal:
651 return new DecimalConstant (target_type, (decimal) Value, Location);
654 return null;
659 public class CharConstant : Constant {
660 public readonly char Value;
662 public CharConstant (BuiltinTypes types, char v, Location loc)
663 : this (types.Char, v, loc)
667 public CharConstant (TypeSpec type, char v, Location loc)
668 : base (loc)
670 this.type = type;
671 eclass = ExprClass.Value;
673 Value = v;
676 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
678 enc.Encode ((ushort) Value);
681 public override void Emit (EmitContext ec)
683 ec.EmitInt (Value);
686 static string descape (char c)
688 switch (c){
689 case '\a':
690 return "\\a";
691 case '\b':
692 return "\\b";
693 case '\n':
694 return "\\n";
695 case '\t':
696 return "\\t";
697 case '\v':
698 return "\\v";
699 case '\r':
700 return "\\r";
701 case '\\':
702 return "\\\\";
703 case '\f':
704 return "\\f";
705 case '\0':
706 return "\\0";
707 case '"':
708 return "\\\"";
709 case '\'':
710 return "\\\'";
712 return c.ToString ();
715 public override object GetValue ()
717 return Value;
720 public override long GetValueAsLong ()
722 return Value;
725 public override string GetValueAsLiteral ()
727 return "\"" + descape (Value) + "\"";
730 public override bool IsDefaultValue {
731 get {
732 return Value == 0;
736 public override bool IsNegative {
737 get {
738 return false;
742 public override bool IsZeroInteger {
743 get { return Value == '\0'; }
746 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
748 switch (target_type.BuiltinType) {
749 case BuiltinTypeSpec.Type.Byte:
750 if (in_checked_context) {
751 if (Value < Byte.MinValue || Value > Byte.MaxValue)
752 throw new OverflowException ();
754 return new ByteConstant (target_type, (byte) Value, Location);
755 case BuiltinTypeSpec.Type.SByte:
756 if (in_checked_context) {
757 if (Value > SByte.MaxValue)
758 throw new OverflowException ();
760 return new SByteConstant (target_type, (sbyte) Value, Location);
762 case BuiltinTypeSpec.Type.Short:
763 if (in_checked_context) {
764 if (Value > Int16.MaxValue)
765 throw new OverflowException ();
767 return new ShortConstant (target_type, (short) Value, Location);
768 case BuiltinTypeSpec.Type.Int:
769 return new IntConstant (target_type, (int) Value, Location);
770 case BuiltinTypeSpec.Type.UInt:
771 return new UIntConstant (target_type, (uint) Value, Location);
772 case BuiltinTypeSpec.Type.Long:
773 return new LongConstant (target_type, (long) Value, Location);
774 case BuiltinTypeSpec.Type.ULong:
775 return new ULongConstant (target_type, (ulong) Value, Location);
776 case BuiltinTypeSpec.Type.Float:
777 return new FloatConstant (target_type, (float) Value, Location);
778 case BuiltinTypeSpec.Type.Double:
779 return new DoubleConstant (target_type, (double) Value, Location);
780 case BuiltinTypeSpec.Type.Decimal:
781 return new DecimalConstant (target_type, (decimal) Value, Location);
784 return null;
789 public class SByteConstant : IntegralConstant
791 public readonly sbyte Value;
793 public SByteConstant (BuiltinTypes types, sbyte v, Location loc)
794 : this (types.SByte, v, loc)
798 public SByteConstant (TypeSpec type, sbyte v, Location loc)
799 : base (type, loc)
801 Value = v;
804 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
806 enc.Encode (Value);
809 public override void Emit (EmitContext ec)
811 ec.EmitInt (Value);
814 public override object GetValue ()
816 return Value;
819 public override long GetValueAsLong ()
821 return Value;
824 public override Constant Increment ()
826 return new SByteConstant (type, checked((sbyte)(Value + 1)), loc);
829 public override bool IsDefaultValue {
830 get {
831 return Value == 0;
835 public override bool IsNegative {
836 get {
837 return Value < 0;
841 public override bool IsOneInteger {
842 get {
843 return Value == 1;
847 public override bool IsZeroInteger {
848 get { return Value == 0; }
851 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
853 switch (target_type.BuiltinType) {
854 case BuiltinTypeSpec.Type.Byte:
855 if (in_checked_context && Value < 0)
856 throw new OverflowException ();
857 return new ByteConstant (target_type, (byte) Value, Location);
858 case BuiltinTypeSpec.Type.Short:
859 return new ShortConstant (target_type, (short) Value, Location);
860 case BuiltinTypeSpec.Type.UShort:
861 if (in_checked_context && Value < 0)
862 throw new OverflowException ();
863 return new UShortConstant (target_type, (ushort) Value, Location);
864 case BuiltinTypeSpec.Type.Int:
865 return new IntConstant (target_type, (int) Value, Location);
866 case BuiltinTypeSpec.Type.UInt:
867 if (in_checked_context && Value < 0)
868 throw new OverflowException ();
869 return new UIntConstant (target_type, (uint) Value, Location);
870 case BuiltinTypeSpec.Type.Long:
871 return new LongConstant (target_type, (long) Value, Location);
872 case BuiltinTypeSpec.Type.ULong:
873 if (in_checked_context && Value < 0)
874 throw new OverflowException ();
875 return new ULongConstant (target_type, (ulong) Value, Location);
876 case BuiltinTypeSpec.Type.Float:
877 return new FloatConstant (target_type, (float) Value, Location);
878 case BuiltinTypeSpec.Type.Double:
879 return new DoubleConstant (target_type, (double) Value, Location);
880 case BuiltinTypeSpec.Type.Char:
881 if (in_checked_context && Value < 0)
882 throw new OverflowException ();
883 return new CharConstant (target_type, (char) Value, Location);
884 case BuiltinTypeSpec.Type.Decimal:
885 return new DecimalConstant (target_type, (decimal) Value, Location);
888 return null;
893 public class ShortConstant : IntegralConstant {
894 public readonly short Value;
896 public ShortConstant (BuiltinTypes types, short v, Location loc)
897 : this (types.Short, v, loc)
901 public ShortConstant (TypeSpec type, short v, Location loc)
902 : base (type, loc)
904 Value = v;
907 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
909 enc.Encode (Value);
912 public override void Emit (EmitContext ec)
914 ec.EmitInt (Value);
917 public override object GetValue ()
919 return Value;
922 public override long GetValueAsLong ()
924 return Value;
927 public override Constant Increment ()
929 return new ShortConstant (type, checked((short)(Value + 1)), loc);
932 public override bool IsDefaultValue {
933 get {
934 return Value == 0;
938 public override bool IsZeroInteger {
939 get { return Value == 0; }
942 public override bool IsNegative {
943 get {
944 return Value < 0;
948 public override bool IsOneInteger {
949 get {
950 return Value == 1;
954 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
956 switch (target_type.BuiltinType) {
957 case BuiltinTypeSpec.Type.Byte:
958 if (in_checked_context) {
959 if (Value < Byte.MinValue || Value > Byte.MaxValue)
960 throw new OverflowException ();
962 return new ByteConstant (target_type, (byte) Value, Location);
963 case BuiltinTypeSpec.Type.SByte:
964 if (in_checked_context) {
965 if (Value < SByte.MinValue || Value > SByte.MaxValue)
966 throw new OverflowException ();
968 return new SByteConstant (target_type, (sbyte) Value, Location);
969 case BuiltinTypeSpec.Type.UShort:
970 if (in_checked_context && Value < 0)
971 throw new OverflowException ();
973 return new UShortConstant (target_type, (ushort) Value, Location);
974 case BuiltinTypeSpec.Type.Int:
975 return new IntConstant (target_type, (int) Value, Location);
976 case BuiltinTypeSpec.Type.UInt:
977 if (in_checked_context && Value < 0)
978 throw new OverflowException ();
979 return new UIntConstant (target_type, (uint) Value, Location);
980 case BuiltinTypeSpec.Type.Long:
981 return new LongConstant (target_type, (long) Value, Location);
982 case BuiltinTypeSpec.Type.ULong:
983 if (in_checked_context && Value < 0)
984 throw new OverflowException ();
985 return new ULongConstant (target_type, (ulong) Value, Location);
986 case BuiltinTypeSpec.Type.Float:
987 return new FloatConstant (target_type, (float) Value, Location);
988 case BuiltinTypeSpec.Type.Double:
989 return new DoubleConstant (target_type, (double) Value, Location);
990 case BuiltinTypeSpec.Type.Char:
991 if (in_checked_context) {
992 if (Value < Char.MinValue)
993 throw new OverflowException ();
995 return new CharConstant (target_type, (char) Value, Location);
996 case BuiltinTypeSpec.Type.Decimal:
997 return new DecimalConstant (target_type, (decimal) Value, Location);
1000 return null;
1005 public class UShortConstant : IntegralConstant
1007 public readonly ushort Value;
1009 public UShortConstant (BuiltinTypes types, ushort v, Location loc)
1010 : this (types.UShort, v, loc)
1014 public UShortConstant (TypeSpec type, ushort v, Location loc)
1015 : base (type, loc)
1017 Value = v;
1020 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1022 enc.Encode (Value);
1025 public override void Emit (EmitContext ec)
1027 ec.EmitInt (Value);
1030 public override object GetValue ()
1032 return Value;
1035 public override long GetValueAsLong ()
1037 return Value;
1040 public override Constant Increment ()
1042 return new UShortConstant (type, checked((ushort)(Value + 1)), loc);
1045 public override bool IsDefaultValue {
1046 get {
1047 return Value == 0;
1051 public override bool IsNegative {
1052 get {
1053 return false;
1057 public override bool IsOneInteger {
1058 get {
1059 return Value == 1;
1063 public override bool IsZeroInteger {
1064 get { return Value == 0; }
1067 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1069 switch (target_type.BuiltinType) {
1070 case BuiltinTypeSpec.Type.Byte:
1071 if (in_checked_context) {
1072 if (Value > Byte.MaxValue)
1073 throw new OverflowException ();
1075 return new ByteConstant (target_type, (byte) Value, Location);
1076 case BuiltinTypeSpec.Type.SByte:
1077 if (in_checked_context) {
1078 if (Value > SByte.MaxValue)
1079 throw new OverflowException ();
1081 return new SByteConstant (target_type, (sbyte) Value, Location);
1082 case BuiltinTypeSpec.Type.Short:
1083 if (in_checked_context) {
1084 if (Value > Int16.MaxValue)
1085 throw new OverflowException ();
1087 return new ShortConstant (target_type, (short) Value, Location);
1088 case BuiltinTypeSpec.Type.Int:
1089 return new IntConstant (target_type, (int) Value, Location);
1090 case BuiltinTypeSpec.Type.UInt:
1091 return new UIntConstant (target_type, (uint) Value, Location);
1092 case BuiltinTypeSpec.Type.Long:
1093 return new LongConstant (target_type, (long) Value, Location);
1094 case BuiltinTypeSpec.Type.ULong:
1095 return new ULongConstant (target_type, (ulong) Value, Location);
1096 case BuiltinTypeSpec.Type.Float:
1097 return new FloatConstant (target_type, (float) Value, Location);
1098 case BuiltinTypeSpec.Type.Double:
1099 return new DoubleConstant (target_type, (double) Value, Location);
1100 case BuiltinTypeSpec.Type.Char:
1101 if (in_checked_context) {
1102 if (Value > Char.MaxValue)
1103 throw new OverflowException ();
1105 return new CharConstant (target_type, (char) Value, Location);
1106 case BuiltinTypeSpec.Type.Decimal:
1107 return new DecimalConstant (target_type, (decimal) Value, Location);
1110 return null;
1114 public class IntConstant : IntegralConstant
1116 public readonly int Value;
1118 public IntConstant (BuiltinTypes types, int v, Location loc)
1119 : this (types.Int, v, loc)
1123 public IntConstant (TypeSpec type, int v, Location loc)
1124 : base (type, loc)
1126 Value = v;
1129 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1131 enc.Encode (Value);
1134 public override void Emit (EmitContext ec)
1136 ec.EmitInt (Value);
1139 public override object GetValue ()
1141 return Value;
1144 public override long GetValueAsLong ()
1146 return Value;
1149 public override Constant Increment ()
1151 return new IntConstant (type, checked(Value + 1), loc);
1154 public override bool IsDefaultValue {
1155 get {
1156 return Value == 0;
1160 public override bool IsNegative {
1161 get {
1162 return Value < 0;
1166 public override bool IsOneInteger {
1167 get {
1168 return Value == 1;
1172 public override bool IsZeroInteger {
1173 get { return Value == 0; }
1176 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1178 switch (target_type.BuiltinType) {
1179 case BuiltinTypeSpec.Type.Byte:
1180 if (in_checked_context) {
1181 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1182 throw new OverflowException ();
1184 return new ByteConstant (target_type, (byte) Value, Location);
1185 case BuiltinTypeSpec.Type.SByte:
1186 if (in_checked_context) {
1187 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1188 throw new OverflowException ();
1190 return new SByteConstant (target_type, (sbyte) Value, Location);
1191 case BuiltinTypeSpec.Type.Short:
1192 if (in_checked_context) {
1193 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1194 throw new OverflowException ();
1196 return new ShortConstant (target_type, (short) Value, Location);
1197 case BuiltinTypeSpec.Type.UShort:
1198 if (in_checked_context) {
1199 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1200 throw new OverflowException ();
1202 return new UShortConstant (target_type, (ushort) Value, Location);
1203 case BuiltinTypeSpec.Type.UInt:
1204 if (in_checked_context) {
1205 if (Value < UInt32.MinValue)
1206 throw new OverflowException ();
1208 return new UIntConstant (target_type, (uint) Value, Location);
1209 case BuiltinTypeSpec.Type.Long:
1210 return new LongConstant (target_type, (long) Value, Location);
1211 case BuiltinTypeSpec.Type.ULong:
1212 if (in_checked_context && Value < 0)
1213 throw new OverflowException ();
1214 return new ULongConstant (target_type, (ulong) Value, Location);
1215 case BuiltinTypeSpec.Type.Float:
1216 return new FloatConstant (target_type, (float) Value, Location);
1217 case BuiltinTypeSpec.Type.Double:
1218 return new DoubleConstant (target_type, (double) Value, Location);
1219 case BuiltinTypeSpec.Type.Char:
1220 if (in_checked_context) {
1221 if (Value < Char.MinValue || Value > Char.MaxValue)
1222 throw new OverflowException ();
1224 return new CharConstant (target_type, (char) Value, Location);
1225 case BuiltinTypeSpec.Type.Decimal:
1226 return new DecimalConstant (target_type, (decimal) Value, Location);
1229 return null;
1232 public override Constant ConvertImplicitly (TypeSpec type)
1234 if (this.type == type)
1235 return this;
1237 Constant c = TryImplicitIntConversion (type);
1238 if (c != null)
1239 return c; //.Resolve (rc);
1241 return base.ConvertImplicitly (type);
1244 /// <summary>
1245 /// Attempts to perform an implicit constant conversion of the IntConstant
1246 /// into a different data type using casts (See Implicit Constant
1247 /// Expression Conversions)
1248 /// </summary>
1249 Constant TryImplicitIntConversion (TypeSpec target_type)
1251 switch (target_type.BuiltinType) {
1252 case BuiltinTypeSpec.Type.SByte:
1253 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1254 return new SByteConstant (target_type, (sbyte) Value, loc);
1255 break;
1256 case BuiltinTypeSpec.Type.Byte:
1257 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1258 return new ByteConstant (target_type, (byte) Value, loc);
1259 break;
1260 case BuiltinTypeSpec.Type.Short:
1261 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1262 return new ShortConstant (target_type, (short) Value, loc);
1263 break;
1264 case BuiltinTypeSpec.Type.UShort:
1265 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1266 return new UShortConstant (target_type, (ushort) Value, loc);
1267 break;
1268 case BuiltinTypeSpec.Type.UInt:
1269 if (Value >= 0)
1270 return new UIntConstant (target_type, (uint) Value, loc);
1271 break;
1272 case BuiltinTypeSpec.Type.ULong:
1274 // we can optimize this case: a positive int32
1275 // always fits on a uint64. But we need an opcode
1276 // to do it.
1278 if (Value >= 0)
1279 return new ULongConstant (target_type, (ulong) Value, loc);
1280 break;
1281 case BuiltinTypeSpec.Type.Double:
1282 return new DoubleConstant (target_type, (double) Value, loc);
1283 case BuiltinTypeSpec.Type.Float:
1284 return new FloatConstant (target_type, (float) Value, loc);
1287 return null;
1291 public class UIntConstant : IntegralConstant {
1292 public readonly uint Value;
1294 public UIntConstant (BuiltinTypes types, uint v, Location loc)
1295 : this (types.UInt, v, loc)
1299 public UIntConstant (TypeSpec type, uint v, Location loc)
1300 : base (type, loc)
1302 Value = v;
1305 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1307 enc.Encode (Value);
1310 public override void Emit (EmitContext ec)
1312 ec.EmitInt (unchecked ((int) Value));
1315 public override object GetValue ()
1317 return Value;
1320 public override long GetValueAsLong ()
1322 return Value;
1325 public override Constant Increment ()
1327 return new UIntConstant (type, checked(Value + 1), loc);
1330 public override bool IsDefaultValue {
1331 get {
1332 return Value == 0;
1336 public override bool IsNegative {
1337 get {
1338 return false;
1342 public override bool IsOneInteger {
1343 get {
1344 return Value == 1;
1348 public override bool IsZeroInteger {
1349 get { return Value == 0; }
1352 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1354 switch (target_type.BuiltinType) {
1355 case BuiltinTypeSpec.Type.Byte:
1356 if (in_checked_context) {
1357 if (Value < 0 || Value > byte.MaxValue)
1358 throw new OverflowException ();
1360 return new ByteConstant (target_type, (byte) Value, Location);
1361 case BuiltinTypeSpec.Type.SByte:
1362 if (in_checked_context) {
1363 if (Value > SByte.MaxValue)
1364 throw new OverflowException ();
1366 return new SByteConstant (target_type, (sbyte) Value, Location);
1367 case BuiltinTypeSpec.Type.Short:
1368 if (in_checked_context) {
1369 if (Value > Int16.MaxValue)
1370 throw new OverflowException ();
1372 return new ShortConstant (target_type, (short) Value, Location);
1373 case BuiltinTypeSpec.Type.UShort:
1374 if (in_checked_context) {
1375 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1376 throw new OverflowException ();
1378 return new UShortConstant (target_type, (ushort) Value, Location);
1379 case BuiltinTypeSpec.Type.Int:
1380 if (in_checked_context) {
1381 if (Value > Int32.MaxValue)
1382 throw new OverflowException ();
1384 return new IntConstant (target_type, (int) Value, Location);
1385 case BuiltinTypeSpec.Type.Long:
1386 return new LongConstant (target_type, (long) Value, Location);
1387 case BuiltinTypeSpec.Type.ULong:
1388 return new ULongConstant (target_type, (ulong) Value, Location);
1389 case BuiltinTypeSpec.Type.Float:
1390 return new FloatConstant (target_type, (float) Value, Location);
1391 case BuiltinTypeSpec.Type.Double:
1392 return new DoubleConstant (target_type, (double) Value, Location);
1393 case BuiltinTypeSpec.Type.Char:
1394 if (in_checked_context) {
1395 if (Value < Char.MinValue || Value > Char.MaxValue)
1396 throw new OverflowException ();
1398 return new CharConstant (target_type, (char) Value, Location);
1399 case BuiltinTypeSpec.Type.Decimal:
1400 return new DecimalConstant (target_type, (decimal) Value, Location);
1403 return null;
1408 public class LongConstant : IntegralConstant {
1409 public readonly long Value;
1411 public LongConstant (BuiltinTypes types, long v, Location loc)
1412 : this (types.Long, v, loc)
1416 public LongConstant (TypeSpec type, long v, Location loc)
1417 : base (type, loc)
1419 Value = v;
1422 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1424 enc.Encode (Value);
1427 public override void Emit (EmitContext ec)
1429 ec.EmitLong (Value);
1432 public override object GetValue ()
1434 return Value;
1437 public override long GetValueAsLong ()
1439 return Value;
1442 public override Constant Increment ()
1444 return new LongConstant (type, checked(Value + 1), loc);
1447 public override bool IsDefaultValue {
1448 get {
1449 return Value == 0;
1453 public override bool IsNegative {
1454 get {
1455 return Value < 0;
1459 public override bool IsOneInteger {
1460 get {
1461 return Value == 1;
1465 public override bool IsZeroInteger {
1466 get { return Value == 0; }
1469 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1471 switch (target_type.BuiltinType) {
1472 case BuiltinTypeSpec.Type.Byte:
1473 if (in_checked_context) {
1474 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1475 throw new OverflowException ();
1477 return new ByteConstant (target_type, (byte) Value, Location);
1478 case BuiltinTypeSpec.Type.SByte:
1479 if (in_checked_context) {
1480 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1481 throw new OverflowException ();
1483 return new SByteConstant (target_type, (sbyte) Value, Location);
1484 case BuiltinTypeSpec.Type.Short:
1485 if (in_checked_context) {
1486 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1487 throw new OverflowException ();
1489 return new ShortConstant (target_type, (short) Value, Location);
1490 case BuiltinTypeSpec.Type.UShort:
1491 if (in_checked_context) {
1492 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1493 throw new OverflowException ();
1495 return new UShortConstant (target_type, (ushort) Value, Location);
1496 case BuiltinTypeSpec.Type.Int:
1497 if (in_checked_context) {
1498 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1499 throw new OverflowException ();
1501 return new IntConstant (target_type, (int) Value, Location);
1502 case BuiltinTypeSpec.Type.UInt:
1503 if (in_checked_context) {
1504 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1505 throw new OverflowException ();
1507 return new UIntConstant (target_type, (uint) Value, Location);
1508 case BuiltinTypeSpec.Type.ULong:
1509 if (in_checked_context && Value < 0)
1510 throw new OverflowException ();
1511 return new ULongConstant (target_type, (ulong) Value, Location);
1512 case BuiltinTypeSpec.Type.Float:
1513 return new FloatConstant (target_type, (float) Value, Location);
1514 case BuiltinTypeSpec.Type.Double:
1515 return new DoubleConstant (target_type, (double) Value, Location);
1516 case BuiltinTypeSpec.Type.Char:
1517 if (in_checked_context) {
1518 if (Value < Char.MinValue || Value > Char.MaxValue)
1519 throw new OverflowException ();
1521 return new CharConstant (target_type, (char) Value, Location);
1522 case BuiltinTypeSpec.Type.Decimal:
1523 return new DecimalConstant (target_type, (decimal) Value, Location);
1526 return null;
1529 public override Constant ConvertImplicitly (TypeSpec type)
1531 if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) {
1532 return new ULongConstant (type, (ulong) Value, loc);
1535 return base.ConvertImplicitly (type);
1539 public class ULongConstant : IntegralConstant {
1540 public readonly ulong Value;
1542 public ULongConstant (BuiltinTypes types, ulong v, Location loc)
1543 : this (types.ULong, v, loc)
1547 public ULongConstant (TypeSpec type, ulong v, Location loc)
1548 : base (type, loc)
1550 Value = v;
1553 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1555 enc.Encode (Value);
1558 public override void Emit (EmitContext ec)
1560 ec.EmitLong (unchecked ((long) Value));
1563 public override object GetValue ()
1565 return Value;
1568 public override long GetValueAsLong ()
1570 return (long) Value;
1573 public override Constant Increment ()
1575 return new ULongConstant (type, checked(Value + 1), loc);
1578 public override bool IsDefaultValue {
1579 get {
1580 return Value == 0;
1584 public override bool IsNegative {
1585 get {
1586 return false;
1590 public override bool IsOneInteger {
1591 get {
1592 return Value == 1;
1596 public override bool IsZeroInteger {
1597 get { return Value == 0; }
1600 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1602 switch (target_type.BuiltinType) {
1603 case BuiltinTypeSpec.Type.Byte:
1604 if (in_checked_context && Value > Byte.MaxValue)
1605 throw new OverflowException ();
1606 return new ByteConstant (target_type, (byte) Value, Location);
1607 case BuiltinTypeSpec.Type.SByte:
1608 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1609 throw new OverflowException ();
1610 return new SByteConstant (target_type, (sbyte) Value, Location);
1611 case BuiltinTypeSpec.Type.Short:
1612 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1613 throw new OverflowException ();
1614 return new ShortConstant (target_type, (short) Value, Location);
1615 case BuiltinTypeSpec.Type.UShort:
1616 if (in_checked_context && Value > UInt16.MaxValue)
1617 throw new OverflowException ();
1618 return new UShortConstant (target_type, (ushort) Value, Location);
1619 case BuiltinTypeSpec.Type.Int:
1620 if (in_checked_context && Value > UInt32.MaxValue)
1621 throw new OverflowException ();
1622 return new IntConstant (target_type, (int) Value, Location);
1623 case BuiltinTypeSpec.Type.UInt:
1624 if (in_checked_context && Value > UInt32.MaxValue)
1625 throw new OverflowException ();
1626 return new UIntConstant (target_type, (uint) Value, Location);
1627 case BuiltinTypeSpec.Type.Long:
1628 if (in_checked_context && Value > Int64.MaxValue)
1629 throw new OverflowException ();
1630 return new LongConstant (target_type, (long) Value, Location);
1631 case BuiltinTypeSpec.Type.Float:
1632 return new FloatConstant (target_type, (float) Value, Location);
1633 case BuiltinTypeSpec.Type.Double:
1634 return new DoubleConstant (target_type, (double) Value, Location);
1635 case BuiltinTypeSpec.Type.Char:
1636 if (in_checked_context && Value > Char.MaxValue)
1637 throw new OverflowException ();
1638 return new CharConstant (target_type, (char) Value, Location);
1639 case BuiltinTypeSpec.Type.Decimal:
1640 return new DecimalConstant (target_type, (decimal) Value, Location);
1643 return null;
1648 public class FloatConstant : Constant {
1650 // Store constant value as double because float constant operations
1651 // need to work on double value to match JIT
1653 public readonly double DoubleValue;
1655 public FloatConstant (BuiltinTypes types, double v, Location loc)
1656 : this (types.Float, v, loc)
1660 public FloatConstant (TypeSpec type, double v, Location loc)
1661 : base (loc)
1663 this.type = type;
1664 eclass = ExprClass.Value;
1666 DoubleValue = v;
1669 public override Constant ConvertImplicitly (TypeSpec type)
1671 if (type.BuiltinType == BuiltinTypeSpec.Type.Double)
1672 return new DoubleConstant (type, DoubleValue, loc);
1674 return base.ConvertImplicitly (type);
1677 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1679 enc.Encode (Value);
1682 public override void Emit (EmitContext ec)
1684 ec.Emit (OpCodes.Ldc_R4, Value);
1687 public float Value {
1688 get {
1689 return (float) DoubleValue;
1693 public override object GetValue ()
1695 return Value;
1698 public override string GetValueAsLiteral ()
1700 return Value.ToString (CultureInfo.InvariantCulture);
1703 public override long GetValueAsLong ()
1705 throw new NotSupportedException ();
1708 public override bool IsDefaultValue {
1709 get {
1710 return Value == 0;
1714 public override bool IsNegative {
1715 get {
1716 return Value < 0;
1720 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1722 switch (target_type.BuiltinType) {
1723 case BuiltinTypeSpec.Type.Byte:
1724 if (in_checked_context) {
1725 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1726 throw new OverflowException ();
1728 return new ByteConstant (target_type, (byte) DoubleValue, Location);
1729 case BuiltinTypeSpec.Type.SByte:
1730 if (in_checked_context) {
1731 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1732 throw new OverflowException ();
1734 return new SByteConstant (target_type, (sbyte) DoubleValue, Location);
1735 case BuiltinTypeSpec.Type.Short:
1736 if (in_checked_context) {
1737 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1738 throw new OverflowException ();
1740 return new ShortConstant (target_type, (short) DoubleValue, Location);
1741 case BuiltinTypeSpec.Type.UShort:
1742 if (in_checked_context) {
1743 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1744 throw new OverflowException ();
1746 return new UShortConstant (target_type, (ushort) DoubleValue, Location);
1747 case BuiltinTypeSpec.Type.Int:
1748 if (in_checked_context) {
1749 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1750 throw new OverflowException ();
1752 return new IntConstant (target_type, (int) DoubleValue, Location);
1753 case BuiltinTypeSpec.Type.UInt:
1754 if (in_checked_context) {
1755 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1756 throw new OverflowException ();
1758 return new UIntConstant (target_type, (uint) DoubleValue, Location);
1759 case BuiltinTypeSpec.Type.Long:
1760 if (in_checked_context) {
1761 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1762 throw new OverflowException ();
1764 return new LongConstant (target_type, (long) DoubleValue, Location);
1765 case BuiltinTypeSpec.Type.ULong:
1766 if (in_checked_context) {
1767 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1768 throw new OverflowException ();
1770 return new ULongConstant (target_type, (ulong) DoubleValue, Location);
1771 case BuiltinTypeSpec.Type.Double:
1772 return new DoubleConstant (target_type, DoubleValue, Location);
1773 case BuiltinTypeSpec.Type.Char:
1774 if (in_checked_context) {
1775 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1776 throw new OverflowException ();
1778 return new CharConstant (target_type, (char) DoubleValue, Location);
1779 case BuiltinTypeSpec.Type.Decimal:
1780 return new DecimalConstant (target_type, (decimal) DoubleValue, Location);
1783 return null;
1788 public class DoubleConstant : Constant
1790 public readonly double Value;
1792 public DoubleConstant (BuiltinTypes types, double v, Location loc)
1793 : this (types.Double, v, loc)
1797 public DoubleConstant (TypeSpec type, double v, Location loc)
1798 : base (loc)
1800 this.type = type;
1801 eclass = ExprClass.Value;
1803 Value = v;
1806 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1808 enc.Encode (Value);
1811 public override void Emit (EmitContext ec)
1813 ec.Emit (OpCodes.Ldc_R8, Value);
1816 public override object GetValue ()
1818 return Value;
1821 public override string GetValueAsLiteral ()
1823 return Value.ToString (CultureInfo.InvariantCulture);
1826 public override long GetValueAsLong ()
1828 throw new NotSupportedException ();
1831 public override bool IsDefaultValue {
1832 get {
1833 return Value == 0;
1837 public override bool IsNegative {
1838 get {
1839 return Value < 0;
1843 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1845 switch (target_type.BuiltinType) {
1846 case BuiltinTypeSpec.Type.Byte:
1847 if (in_checked_context) {
1848 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1849 throw new OverflowException ();
1851 return new ByteConstant (target_type, (byte) Value, Location);
1852 case BuiltinTypeSpec.Type.SByte:
1853 if (in_checked_context) {
1854 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1855 throw new OverflowException ();
1857 return new SByteConstant (target_type, (sbyte) Value, Location);
1858 case BuiltinTypeSpec.Type.Short:
1859 if (in_checked_context) {
1860 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1861 throw new OverflowException ();
1863 return new ShortConstant (target_type, (short) Value, Location);
1864 case BuiltinTypeSpec.Type.UShort:
1865 if (in_checked_context) {
1866 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1867 throw new OverflowException ();
1869 return new UShortConstant (target_type, (ushort) Value, Location);
1870 case BuiltinTypeSpec.Type.Int:
1871 if (in_checked_context) {
1872 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1873 throw new OverflowException ();
1875 return new IntConstant (target_type, (int) Value, Location);
1876 case BuiltinTypeSpec.Type.UInt:
1877 if (in_checked_context) {
1878 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1879 throw new OverflowException ();
1881 return new UIntConstant (target_type, (uint) Value, Location);
1882 case BuiltinTypeSpec.Type.Long:
1883 if (in_checked_context) {
1884 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1885 throw new OverflowException ();
1887 return new LongConstant (target_type, (long) Value, Location);
1888 case BuiltinTypeSpec.Type.ULong:
1889 if (in_checked_context) {
1890 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1891 throw new OverflowException ();
1893 return new ULongConstant (target_type, (ulong) Value, Location);
1894 case BuiltinTypeSpec.Type.Float:
1895 return new FloatConstant (target_type, (float) Value, Location);
1896 case BuiltinTypeSpec.Type.Char:
1897 if (in_checked_context) {
1898 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1899 throw new OverflowException ();
1901 return new CharConstant (target_type, (char) Value, Location);
1902 case BuiltinTypeSpec.Type.Decimal:
1903 return new DecimalConstant (target_type, (decimal) Value, Location);
1906 return null;
1911 public class DecimalConstant : Constant {
1912 public readonly decimal Value;
1914 public DecimalConstant (BuiltinTypes types, decimal d, Location loc)
1915 : this (types.Decimal, d, loc)
1919 public DecimalConstant (TypeSpec type, decimal d, Location loc)
1920 : base (loc)
1922 this.type = type;
1923 eclass = ExprClass.Value;
1925 Value = d;
1928 public override void Emit (EmitContext ec)
1930 MethodSpec m;
1932 int [] words = decimal.GetBits (Value);
1933 int power = (words [3] >> 16) & 0xff;
1935 if (power == 0) {
1936 if (Value <= int.MaxValue && Value >= int.MinValue) {
1937 m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc);
1938 if (m == null) {
1939 return;
1942 ec.EmitInt ((int) Value);
1943 ec.Emit (OpCodes.Newobj, m);
1944 return;
1947 if (Value <= long.MaxValue && Value >= long.MinValue) {
1948 m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc);
1949 if (m == null) {
1950 return;
1953 ec.EmitLong ((long) Value);
1954 ec.Emit (OpCodes.Newobj, m);
1955 return;
1959 ec.EmitInt (words [0]);
1960 ec.EmitInt (words [1]);
1961 ec.EmitInt (words [2]);
1963 // sign
1964 ec.EmitInt (words [3] >> 31);
1966 // power
1967 ec.EmitInt (power);
1969 m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc);
1970 if (m != null) {
1971 ec.Emit (OpCodes.Newobj, m);
1975 public override bool IsDefaultValue {
1976 get {
1977 return Value == 0;
1981 public override bool IsNegative {
1982 get {
1983 return Value < 0;
1987 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1989 switch (target_type.BuiltinType) {
1990 case BuiltinTypeSpec.Type.SByte:
1991 return new SByteConstant (target_type, (sbyte) Value, loc);
1992 case BuiltinTypeSpec.Type.Byte:
1993 return new ByteConstant (target_type, (byte) Value, loc);
1994 case BuiltinTypeSpec.Type.Short:
1995 return new ShortConstant (target_type, (short) Value, loc);
1996 case BuiltinTypeSpec.Type.UShort:
1997 return new UShortConstant (target_type, (ushort) Value, loc);
1998 case BuiltinTypeSpec.Type.Int:
1999 return new IntConstant (target_type, (int) Value, loc);
2000 case BuiltinTypeSpec.Type.UInt:
2001 return new UIntConstant (target_type, (uint) Value, loc);
2002 case BuiltinTypeSpec.Type.Long:
2003 return new LongConstant (target_type, (long) Value, loc);
2004 case BuiltinTypeSpec.Type.ULong:
2005 return new ULongConstant (target_type, (ulong) Value, loc);
2006 case BuiltinTypeSpec.Type.Char:
2007 return new CharConstant (target_type, (char) Value, loc);
2008 case BuiltinTypeSpec.Type.Float:
2009 return new FloatConstant (target_type, (float) Value, loc);
2010 case BuiltinTypeSpec.Type.Double:
2011 return new DoubleConstant (target_type, (double) Value, loc);
2014 return null;
2017 public override object GetValue ()
2019 return Value;
2022 public override string GetValueAsLiteral ()
2024 return Value.ToString (CultureInfo.InvariantCulture) + "M";
2027 public override long GetValueAsLong ()
2029 throw new NotSupportedException ();
2033 public class StringConstant : Constant {
2034 public StringConstant (BuiltinTypes types, string s, Location loc)
2035 : this (types.String, s, loc)
2039 public StringConstant (TypeSpec type, string s, Location loc)
2040 : base (loc)
2042 this.type = type;
2043 eclass = ExprClass.Value;
2045 Value = s;
2048 protected StringConstant (Location loc)
2049 : base (loc)
2053 public string Value { get; protected set; }
2055 public override object GetValue ()
2057 return Value;
2060 public override string GetValueAsLiteral ()
2062 // FIXME: Escape the string.
2063 return "\"" + Value + "\"";
2066 public override long GetValueAsLong ()
2068 throw new NotSupportedException ();
2071 public override void Emit (EmitContext ec)
2073 if (Value == null) {
2074 ec.EmitNull ();
2075 return;
2079 // Use string.Empty for both literals and constants even if
2080 // it's not allowed at language level
2082 if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) {
2083 var string_type = ec.BuiltinTypes.String;
2084 if (ec.CurrentType != string_type) {
2085 var m = ec.Module.PredefinedMembers.StringEmpty.Get ();
2086 if (m != null) {
2087 ec.Emit (OpCodes.Ldsfld, m);
2088 return;
2093 var str = Value;
2094 if (ec.Module.GetResourceStrings != null && !ec.Module.GetResourceStrings.TryGetValue (str, out str)) {
2095 str = Value;
2098 ec.Emit (OpCodes.Ldstr, str);
2101 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
2103 // cast to object
2104 if (type != targetType)
2105 enc.Encode (type);
2107 enc.Encode (Value);
2110 public override bool IsDefaultValue {
2111 get {
2112 return Value == null;
2116 public override bool IsNegative {
2117 get {
2118 return false;
2122 public override bool IsNull {
2123 get {
2124 return IsDefaultValue;
2128 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2130 return null;
2133 public override Constant ConvertImplicitly (TypeSpec type)
2135 if (IsDefaultValue && type.BuiltinType == BuiltinTypeSpec.Type.Object)
2136 return new NullConstant (type, loc);
2138 return base.ConvertImplicitly (type);
2142 class NameOf : StringConstant
2144 readonly SimpleName name;
2146 public NameOf (SimpleName name)
2147 : base (name.Location)
2149 this.name = name;
2152 protected override Expression DoResolve (ResolveContext rc)
2154 throw new NotSupportedException ();
2157 bool ResolveArgumentExpression (ResolveContext rc, Expression expr)
2159 var sn = expr as SimpleName;
2160 if (sn != null) {
2161 Value = sn.Name;
2163 if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6)
2164 rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
2166 var res = sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity | MemberLookupRestrictions.NameOfExcluded);
2167 var me = res as MemberExpr;
2168 if (me != null)
2169 me.ResolveNameOf (rc, sn);
2171 return true;
2174 var ma = expr as MemberAccess;
2175 if (ma != null) {
2176 var lexpr = ma.LeftExpression;
2177 Expression res;
2179 using (rc.Set (ResolveContext.Options.NameOfScope)) {
2180 res = ma.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity);
2183 if (res == null) {
2184 return false;
2187 if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6)
2188 rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
2190 if (ma is QualifiedAliasMember) {
2191 rc.Report.Error (8083, loc, "An alias-qualified name is not an expression");
2192 return false;
2195 var me = res as MemberExpr;
2196 if (me != null) {
2197 me.ResolveNameOf (rc, ma);
2201 // LAMESPEC: Why is conditional access not allowed?
2203 if (!IsLeftResolvedExpressionValid (ma.LeftExpression) || ma.HasConditionalAccess ()) {
2204 rc.Report.Error (8082, lexpr.Location, "An argument to nameof operator cannot include sub-expression");
2205 return false;
2208 Value = ma.Name;
2209 return true;
2212 rc.Report.Error (8081, loc, "Expression does not have a name");
2213 return false;
2216 static bool IsLeftResolvedExpressionValid (Expression expr)
2218 var fe = expr as FieldExpr;
2219 if (fe != null) {
2220 return fe.InstanceExpression == null || IsLeftResolvedExpressionValid (fe.InstanceExpression);
2223 var pe = expr as PropertyExpr;
2224 if (pe != null)
2225 return pe.InstanceExpression == null || IsLeftResolvedExpressionValid (pe.InstanceExpression);
2227 var dmb = expr as DynamicMemberBinder;
2228 if (dmb != null) {
2229 return IsLeftResolvedExpressionValid (dmb.Arguments [0].Expr);
2232 if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is VariableReference)
2233 return true;
2235 return false;
2238 public Expression ResolveOverload (ResolveContext rc, Arguments args)
2240 if (args == null || args.Count != 1) {
2241 name.Error_NameDoesNotExist (rc);
2242 return null;
2245 var arg = args [0];
2246 var res = ResolveArgumentExpression (rc, arg.Expr);
2247 if (!res) {
2248 return null;
2251 type = rc.BuiltinTypes.String;
2252 eclass = ExprClass.Value;
2253 return this;
2258 // Null constant can have its own type, think of `default (Foo)'
2260 public class NullConstant : Constant
2262 public NullConstant (TypeSpec type, Location loc)
2263 : base (loc)
2265 eclass = ExprClass.Value;
2266 this.type = type;
2269 public override Expression CreateExpressionTree (ResolveContext ec)
2271 if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2272 // Optimized version, also avoids referencing literal internal type
2273 Arguments args = new Arguments (1);
2274 args.Add (new Argument (this));
2275 return CreateExpressionFactoryCall (ec, "Constant", args);
2278 return base.CreateExpressionTree (ec);
2281 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
2283 switch (targetType.BuiltinType) {
2284 case BuiltinTypeSpec.Type.Object:
2285 // Type it as string cast
2286 enc.Encode (rc.Module.Compiler.BuiltinTypes.String);
2287 goto case BuiltinTypeSpec.Type.String;
2288 case BuiltinTypeSpec.Type.String:
2289 case BuiltinTypeSpec.Type.Type:
2290 enc.Encode (byte.MaxValue);
2291 return;
2292 default:
2293 var ac = targetType as ArrayContainer;
2294 if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) {
2295 enc.Encode (uint.MaxValue);
2296 return;
2299 break;
2302 base.EncodeAttributeValue (rc, enc, targetType, parameterType);
2305 public override void Emit (EmitContext ec)
2307 ec.EmitNull ();
2309 // Only to make verifier happy
2310 if (type.IsGenericParameter)
2311 ec.Emit (OpCodes.Unbox_Any, type);
2314 public override string ExprClassName {
2315 get {
2316 return GetSignatureForError ();
2320 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2322 if (targetType.IsPointer) {
2323 if (IsLiteral || this is NullPointer)
2324 return new NullPointer (targetType, loc);
2326 return null;
2329 // Exlude internal compiler types
2330 if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic)
2331 return null;
2333 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2334 return null;
2336 if (TypeSpec.IsReferenceType (targetType))
2337 return new NullConstant (targetType, loc);
2339 if (targetType.IsNullableType)
2340 return Nullable.LiftedNull.Create (targetType, loc);
2342 return null;
2345 public override Constant ConvertImplicitly (TypeSpec targetType)
2347 return ConvertExplicitly (false, targetType);
2350 public override string GetSignatureForError ()
2352 return "null";
2355 public override object GetValue ()
2357 return null;
2360 public override string GetValueAsLiteral ()
2362 return GetSignatureForError ();
2365 public override long GetValueAsLong ()
2367 throw new NotSupportedException ();
2370 public override bool IsDefaultValue {
2371 get { return true; }
2374 public override bool IsNegative {
2375 get { return false; }
2378 public override bool IsNull {
2379 get { return true; }
2382 public override bool IsZeroInteger {
2383 get { return true; }
2389 // A null constant in a pointer context
2391 class NullPointer : NullConstant
2393 public NullPointer (TypeSpec type, Location loc)
2394 : base (type, loc)
2398 public override Expression CreateExpressionTree (ResolveContext ec)
2400 Error_PointerInsideExpressionTree (ec);
2401 return base.CreateExpressionTree (ec);
2404 public override void Emit (EmitContext ec)
2407 // Emits null pointer
2409 ec.EmitInt (0);
2410 ec.Emit (OpCodes.Conv_U);
2414 /// <summary>
2415 /// The value is constant, but when emitted has a side effect. This is
2416 /// used by BitwiseAnd to ensure that the second expression is invoked
2417 /// regardless of the value of the left side.
2418 /// </summary>
2419 public class SideEffectConstant : Constant
2421 public readonly Constant value;
2422 Expression side_effect;
2424 public SideEffectConstant (Constant value, Expression side_effect, Location loc)
2425 : base (loc)
2427 this.value = value;
2428 type = value.Type;
2429 eclass = ExprClass.Value;
2431 while (side_effect is SideEffectConstant)
2432 side_effect = ((SideEffectConstant) side_effect).side_effect;
2433 this.side_effect = side_effect;
2436 public override bool IsSideEffectFree {
2437 get {
2438 return false;
2442 public override bool ContainsEmitWithAwait ()
2444 return side_effect.ContainsEmitWithAwait ();
2447 public override object GetValue ()
2449 return value.GetValue ();
2452 public override string GetValueAsLiteral ()
2454 return value.GetValueAsLiteral ();
2457 public override long GetValueAsLong ()
2459 return value.GetValueAsLong ();
2462 public override void Emit (EmitContext ec)
2464 side_effect.EmitSideEffect (ec);
2465 value.Emit (ec);
2468 public override void EmitSideEffect (EmitContext ec)
2470 side_effect.EmitSideEffect (ec);
2471 value.EmitSideEffect (ec);
2474 public override void FlowAnalysis (FlowAnalysisContext fc)
2476 side_effect.FlowAnalysis (fc);
2479 public override bool IsDefaultValue {
2480 get { return value.IsDefaultValue; }
2483 public override bool IsNegative {
2484 get { return value.IsNegative; }
2487 public override bool IsZeroInteger {
2488 get { return value.IsZeroInteger; }
2491 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2493 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2494 if (new_value == null)
2495 return null;
2497 var c = new SideEffectConstant (new_value, side_effect, new_value.Location);
2498 c.type = target_type;
2499 c.eclass = eclass;
2500 return c;