2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / constant.cs
blob12c7892d5fe44a39a2d61db05bb1da9427ae4e42
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2001-2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
12 using System;
13 using System.Reflection.Emit;
15 namespace Mono.CSharp {
17 /// <summary>
18 /// Base class for constants and literals.
19 /// </summary>
20 public abstract class Constant : Expression {
22 protected Constant (Location loc)
24 this.loc = loc;
27 /// <remarks>
28 /// This is different from ToString in that ToString
29 /// is supposed to be there for debugging purposes,
30 /// and is not guaranteed to be useful for anything else,
31 /// AsString() will provide something that can be used
32 /// for round-tripping C# code. Maybe it can be used
33 /// for IL assembly as well.
34 /// </remarks>
35 public abstract string AsString ();
37 override public string ToString ()
39 return this.GetType ().Name + " (" + AsString () + ")";
42 public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
44 if (value_type == TypeManager.object_type) {
45 value = GetTypedValue ();
46 return true;
49 Constant c = ImplicitConversionRequired (ec, value_type, loc);
50 if (c == null) {
51 value = null;
52 return false;
55 value = c.GetTypedValue ();
56 return true;
59 /// <summary>
60 /// This is used to obtain the actual value of the literal
61 /// cast into an object.
62 /// </summary>
63 public abstract object GetValue ();
65 public virtual object GetTypedValue ()
67 return GetValue ();
70 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
72 if (!expl && IsLiteral &&
73 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
74 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
75 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
76 AsString (), TypeManager.CSharpName (target));
77 } else {
78 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
82 public Constant ImplicitConversionRequired (ResolveContext ec, Type type, Location loc)
84 Constant c = ConvertImplicitly (ec, type);
85 if (c == null)
86 Error_ValueCannotBeConverted (ec, loc, type, false);
88 return c;
91 public virtual Constant ConvertImplicitly (ResolveContext rc, Type type)
93 if (this.type == type)
94 return this;
96 if (Convert.ImplicitNumericConversion (this, type) == null)
97 return null;
99 bool fail;
100 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
101 if (fail){
103 // We should always catch the error before this is ever
104 // reached, by calling Convert.ImplicitStandardConversionExists
106 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
107 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
110 return CreateConstant (rc, type, constant_value, loc);
114 // Returns a constant instance based on Type
116 public static Constant CreateConstant (ResolveContext rc, Type t, object v, Location loc)
118 return CreateConstantFromValue (t, v, loc).Resolve (rc);
121 public static Constant CreateConstantFromValue (Type t, object v, Location loc)
123 if (t == TypeManager.int32_type)
124 return new IntConstant ((int) v, loc);
125 if (t == TypeManager.string_type)
126 return new StringConstant ((string) v, loc);
127 if (t == TypeManager.uint32_type)
128 return new UIntConstant ((uint) v, loc);
129 if (t == TypeManager.int64_type)
130 return new LongConstant ((long) v, loc);
131 if (t == TypeManager.uint64_type)
132 return new ULongConstant ((ulong) v, loc);
133 if (t == TypeManager.float_type)
134 return new FloatConstant ((float) v, loc);
135 if (t == TypeManager.double_type)
136 return new DoubleConstant ((double) v, loc);
137 if (t == TypeManager.short_type)
138 return new ShortConstant ((short)v, loc);
139 if (t == TypeManager.ushort_type)
140 return new UShortConstant ((ushort)v, loc);
141 if (t == TypeManager.sbyte_type)
142 return new SByteConstant ((sbyte)v, loc);
143 if (t == TypeManager.byte_type)
144 return new ByteConstant ((byte)v, loc);
145 if (t == TypeManager.char_type)
146 return new CharConstant ((char)v, loc);
147 if (t == TypeManager.bool_type)
148 return new BoolConstant ((bool) v, loc);
149 if (t == TypeManager.decimal_type)
150 return new DecimalConstant ((decimal) v, loc);
151 if (TypeManager.IsEnumType (t)) {
152 Type real_type = TypeManager.GetEnumUnderlyingType (t);
153 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
155 if (v == null) {
156 if (TypeManager.IsNullableType (t))
157 return Nullable.LiftedNull.Create (t, loc);
159 if (TypeManager.IsReferenceType (t))
160 return new NullConstant (t, loc);
163 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
164 v, TypeManager.CSharpName (t));
167 public override Expression CreateExpressionTree (ResolveContext ec)
169 Arguments args = new Arguments (2);
170 args.Add (new Argument (this));
171 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
173 return CreateExpressionFactoryCall (ec, "Constant", args);
177 /// <summary>
178 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
179 /// It throws OverflowException
180 /// </summary>
181 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
182 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
184 /// <summary>
185 /// Attempts to do a compile-time folding of a constant cast.
186 /// </summary>
187 public Constant TryReduce (ResolveContext ec, Type target_type, Location loc)
189 try {
190 return TryReduce (ec, target_type);
192 catch (OverflowException) {
193 if (ec.ConstantCheckState) {
194 ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
195 GetValue ().ToString (), TypeManager.CSharpName (target_type));
196 } else {
197 Error_ValueCannotBeConverted (ec, loc, target_type, false);
200 return New.Constantify (target_type).Resolve (ec);
204 Constant TryReduce (ResolveContext ec, Type target_type)
206 if (Type == target_type)
207 return this;
209 Constant c;
210 if (TypeManager.IsEnumType (target_type)) {
211 c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type));
212 if (c == null)
213 return null;
215 return new EnumConstant (c, target_type).Resolve (ec);
218 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
219 if (c != null)
220 c = c.Resolve (ec);
222 return c;
225 /// <summary>
226 /// Need to pass type as the constant can require a boxing
227 /// and in such case no optimization is possible
228 /// </summary>
229 public bool IsDefaultInitializer (Type type)
231 if (type == Type)
232 return IsDefaultValue;
234 return this is NullLiteral;
237 public abstract bool IsDefaultValue {
238 get;
241 public abstract bool IsNegative {
242 get;
246 // When constant is declared as literal
248 public virtual bool IsLiteral {
249 get { return false; }
252 public virtual bool IsOneInteger {
253 get { return false; }
257 // Returns true iff 1) the stack type of this is one of Object,
258 // int32, int64 and 2) this == 0 or this == null.
260 public virtual bool IsZeroInteger {
261 get { return false; }
264 public override void EmitSideEffect (EmitContext ec)
266 // do nothing
269 protected override void CloneTo (CloneContext clonectx, Expression target)
271 // CloneTo: Nothing, we do not keep any state on this expression
274 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
276 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type);
279 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
281 // A constant cannot be of generic type
284 public new Constant Resolve (ResolveContext rc)
286 if (eclass != ExprClass.Unresolved)
287 return this;
289 // Resolved constant has to be still a constant
290 Constant c = (Constant) DoResolve (rc);
291 if (c == null)
292 return null;
294 if ((c.eclass & ExprClass.Value) == 0) {
295 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
296 return null;
299 if (c.type == null)
300 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
302 return c;
306 public abstract class IntegralConstant : Constant {
307 protected IntegralConstant (Location loc) :
308 base (loc)
312 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
314 try {
315 ConvertExplicitly (true, target);
316 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
318 catch
320 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
321 GetValue ().ToString (), TypeManager.CSharpName (target));
325 public abstract Constant Increment ();
328 public class BoolConstant : Constant {
329 public readonly bool Value;
331 public BoolConstant (bool val, Location loc):
332 base (loc)
334 Value = val;
337 override public string AsString ()
339 return Value ? "true" : "false";
342 protected override Expression DoResolve (ResolveContext ec)
344 type = TypeManager.bool_type;
345 eclass = ExprClass.Value;
346 return this;
349 public override object GetValue ()
351 return (object) Value;
354 public override void Emit (EmitContext ec)
356 if (Value)
357 ec.ig.Emit (OpCodes.Ldc_I4_1);
358 else
359 ec.ig.Emit (OpCodes.Ldc_I4_0);
362 public override bool IsDefaultValue {
363 get {
364 return !Value;
368 public override bool IsNegative {
369 get {
370 return false;
374 public override bool IsZeroInteger {
375 get { return Value == false; }
378 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
380 return null;
385 public class ByteConstant : IntegralConstant {
386 public readonly byte Value;
388 public ByteConstant (byte v, Location loc):
389 base (loc)
391 Value = v;
394 public override void Emit (EmitContext ec)
396 IntLiteral.EmitInt (ec.ig, Value);
399 public override string AsString ()
401 return Value.ToString ();
404 protected override Expression DoResolve (ResolveContext ec)
406 type = TypeManager.byte_type;
407 eclass = ExprClass.Value;
408 return this;
411 public override object GetValue ()
413 return Value;
416 public override Constant Increment ()
418 return new ByteConstant (checked ((byte)(Value + 1)), loc);
421 public override bool IsDefaultValue {
422 get {
423 return Value == 0;
427 public override bool IsOneInteger {
428 get {
429 return Value == 1;
433 public override bool IsNegative {
434 get {
435 return false;
439 public override bool IsZeroInteger {
440 get { return Value == 0; }
443 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
445 if (target_type == TypeManager.sbyte_type) {
446 if (in_checked_context){
447 if (Value > SByte.MaxValue)
448 throw new OverflowException ();
450 return new SByteConstant ((sbyte) Value, Location);
452 if (target_type == TypeManager.short_type)
453 return new ShortConstant ((short) Value, Location);
454 if (target_type == TypeManager.ushort_type)
455 return new UShortConstant ((ushort) Value, Location);
456 if (target_type == TypeManager.int32_type)
457 return new IntConstant ((int) Value, Location);
458 if (target_type == TypeManager.uint32_type)
459 return new UIntConstant ((uint) Value, Location);
460 if (target_type == TypeManager.int64_type)
461 return new LongConstant ((long) Value, Location);
462 if (target_type == TypeManager.uint64_type)
463 return new ULongConstant ((ulong) Value, Location);
464 if (target_type == TypeManager.float_type)
465 return new FloatConstant ((float) Value, Location);
466 if (target_type == TypeManager.double_type)
467 return new DoubleConstant ((double) Value, Location);
468 if (target_type == TypeManager.char_type)
469 return new CharConstant ((char) Value, Location);
470 if (target_type == TypeManager.decimal_type)
471 return new DecimalConstant ((decimal) Value, Location);
473 return null;
478 public class CharConstant : Constant {
479 public readonly char Value;
481 public CharConstant (char v, Location loc):
482 base (loc)
484 Value = v;
487 protected override Expression DoResolve (ResolveContext rc)
489 type = TypeManager.char_type;
490 eclass = ExprClass.Value;
491 return this;
494 public override void Emit (EmitContext ec)
496 IntLiteral.EmitInt (ec.ig, Value);
499 static string descape (char c)
501 switch (c){
502 case '\a':
503 return "\\a";
504 case '\b':
505 return "\\b";
506 case '\n':
507 return "\\n";
508 case '\t':
509 return "\\t";
510 case '\v':
511 return "\\v";
512 case '\r':
513 return "\\r";
514 case '\\':
515 return "\\\\";
516 case '\f':
517 return "\\f";
518 case '\0':
519 return "\\0";
520 case '"':
521 return "\\\"";
522 case '\'':
523 return "\\\'";
525 return c.ToString ();
528 public override string AsString ()
530 return "\"" + descape (Value) + "\"";
533 public override object GetValue ()
535 return Value;
538 public override bool IsDefaultValue {
539 get {
540 return Value == 0;
544 public override bool IsNegative {
545 get {
546 return false;
550 public override bool IsZeroInteger {
551 get { return Value == '\0'; }
554 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
556 if (target_type == TypeManager.byte_type) {
557 if (in_checked_context){
558 if (Value < Byte.MinValue || Value > Byte.MaxValue)
559 throw new OverflowException ();
561 return new ByteConstant ((byte) Value, Location);
563 if (target_type == TypeManager.sbyte_type) {
564 if (in_checked_context){
565 if (Value > SByte.MaxValue)
566 throw new OverflowException ();
568 return new SByteConstant ((sbyte) Value, Location);
570 if (target_type == TypeManager.short_type) {
571 if (in_checked_context){
572 if (Value > Int16.MaxValue)
573 throw new OverflowException ();
575 return new ShortConstant ((short) Value, Location);
577 if (target_type == TypeManager.int32_type)
578 return new IntConstant ((int) Value, Location);
579 if (target_type == TypeManager.uint32_type)
580 return new UIntConstant ((uint) Value, Location);
581 if (target_type == TypeManager.int64_type)
582 return new LongConstant ((long) Value, Location);
583 if (target_type == TypeManager.uint64_type)
584 return new ULongConstant ((ulong) Value, Location);
585 if (target_type == TypeManager.float_type)
586 return new FloatConstant ((float) Value, Location);
587 if (target_type == TypeManager.double_type)
588 return new DoubleConstant ((double) Value, Location);
589 if (target_type == TypeManager.decimal_type)
590 return new DecimalConstant ((decimal) Value, Location);
592 return null;
597 public class SByteConstant : IntegralConstant {
598 public readonly sbyte Value;
600 public SByteConstant (sbyte v, Location loc):
601 base (loc)
603 Value = v;
606 protected override Expression DoResolve (ResolveContext rc)
608 type = TypeManager.sbyte_type;
609 eclass = ExprClass.Value;
610 return this;
613 public override void Emit (EmitContext ec)
615 IntLiteral.EmitInt (ec.ig, Value);
618 public override string AsString ()
620 return Value.ToString ();
623 public override object GetValue ()
625 return Value;
628 public override Constant Increment ()
630 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
633 public override bool IsDefaultValue {
634 get {
635 return Value == 0;
639 public override bool IsNegative {
640 get {
641 return Value < 0;
645 public override bool IsOneInteger {
646 get {
647 return Value == 1;
651 public override bool IsZeroInteger {
652 get { return Value == 0; }
655 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
657 if (target_type == TypeManager.byte_type) {
658 if (in_checked_context && Value < 0)
659 throw new OverflowException ();
660 return new ByteConstant ((byte) Value, Location);
662 if (target_type == TypeManager.short_type)
663 return new ShortConstant ((short) Value, Location);
664 if (target_type == TypeManager.ushort_type) {
665 if (in_checked_context && Value < 0)
666 throw new OverflowException ();
667 return new UShortConstant ((ushort) Value, Location);
668 } if (target_type == TypeManager.int32_type)
669 return new IntConstant ((int) Value, Location);
670 if (target_type == TypeManager.uint32_type) {
671 if (in_checked_context && Value < 0)
672 throw new OverflowException ();
673 return new UIntConstant ((uint) Value, Location);
674 } if (target_type == TypeManager.int64_type)
675 return new LongConstant ((long) Value, Location);
676 if (target_type == TypeManager.uint64_type) {
677 if (in_checked_context && Value < 0)
678 throw new OverflowException ();
679 return new ULongConstant ((ulong) Value, Location);
681 if (target_type == TypeManager.float_type)
682 return new FloatConstant ((float) Value, Location);
683 if (target_type == TypeManager.double_type)
684 return new DoubleConstant ((double) Value, Location);
685 if (target_type == TypeManager.char_type) {
686 if (in_checked_context && Value < 0)
687 throw new OverflowException ();
688 return new CharConstant ((char) Value, Location);
690 if (target_type == TypeManager.decimal_type)
691 return new DecimalConstant ((decimal) Value, Location);
693 return null;
698 public class ShortConstant : IntegralConstant {
699 public readonly short Value;
701 public ShortConstant (short v, Location loc):
702 base (loc)
704 Value = v;
707 protected override Expression DoResolve (ResolveContext rc)
709 type = TypeManager.short_type;
710 eclass = ExprClass.Value;
711 return this;
714 public override void Emit (EmitContext ec)
716 IntLiteral.EmitInt (ec.ig, Value);
719 public override string AsString ()
721 return Value.ToString ();
724 public override object GetValue ()
726 return Value;
729 public override Constant Increment ()
731 return new ShortConstant (checked((short)(Value + 1)), loc);
734 public override bool IsDefaultValue {
735 get {
736 return Value == 0;
740 public override bool IsZeroInteger {
741 get { return Value == 0; }
744 public override bool IsNegative {
745 get {
746 return Value < 0;
750 public override bool IsOneInteger {
751 get {
752 return Value == 1;
756 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
758 if (target_type == TypeManager.byte_type) {
759 if (in_checked_context){
760 if (Value < Byte.MinValue || Value > Byte.MaxValue)
761 throw new OverflowException ();
763 return new ByteConstant ((byte) Value, Location);
765 if (target_type == TypeManager.sbyte_type) {
766 if (in_checked_context){
767 if (Value < SByte.MinValue || Value > SByte.MaxValue)
768 throw new OverflowException ();
770 return new SByteConstant ((sbyte) Value, Location);
772 if (target_type == TypeManager.ushort_type) {
773 if (in_checked_context && Value < 0)
774 throw new OverflowException ();
776 return new UShortConstant ((ushort) Value, Location);
778 if (target_type == TypeManager.int32_type)
779 return new IntConstant ((int) Value, Location);
780 if (target_type == TypeManager.uint32_type) {
781 if (in_checked_context && Value < 0)
782 throw new OverflowException ();
783 return new UIntConstant ((uint) Value, Location);
785 if (target_type == TypeManager.int64_type)
786 return new LongConstant ((long) Value, Location);
787 if (target_type == TypeManager.uint64_type) {
788 if (in_checked_context && Value < 0)
789 throw new OverflowException ();
790 return new ULongConstant ((ulong) Value, Location);
792 if (target_type == TypeManager.float_type)
793 return new FloatConstant ((float) Value, Location);
794 if (target_type == TypeManager.double_type)
795 return new DoubleConstant ((double) Value, Location);
796 if (target_type == TypeManager.char_type) {
797 if (in_checked_context){
798 if (Value < Char.MinValue)
799 throw new OverflowException ();
801 return new CharConstant ((char) Value, Location);
803 if (target_type == TypeManager.decimal_type)
804 return new DecimalConstant ((decimal) Value, Location);
806 return null;
811 public class UShortConstant : IntegralConstant {
812 public readonly ushort Value;
814 public UShortConstant (ushort v, Location loc):
815 base (loc)
817 Value = v;
820 protected override Expression DoResolve (ResolveContext rc)
822 type = TypeManager.ushort_type;
823 eclass = ExprClass.Value;
824 return this;
827 public override void Emit (EmitContext ec)
829 IntLiteral.EmitInt (ec.ig, Value);
832 public override string AsString ()
834 return Value.ToString ();
837 public override object GetValue ()
839 return Value;
842 public override Constant Increment ()
844 return new UShortConstant (checked((ushort)(Value + 1)), loc);
847 public override bool IsDefaultValue {
848 get {
849 return Value == 0;
853 public override bool IsNegative {
854 get {
855 return false;
859 public override bool IsOneInteger {
860 get {
861 return Value == 1;
865 public override bool IsZeroInteger {
866 get { return Value == 0; }
869 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
871 if (target_type == TypeManager.byte_type) {
872 if (in_checked_context){
873 if (Value > Byte.MaxValue)
874 throw new OverflowException ();
876 return new ByteConstant ((byte) Value, Location);
878 if (target_type == TypeManager.sbyte_type) {
879 if (in_checked_context){
880 if (Value > SByte.MaxValue)
881 throw new OverflowException ();
883 return new SByteConstant ((sbyte) Value, Location);
885 if (target_type == TypeManager.short_type) {
886 if (in_checked_context){
887 if (Value > Int16.MaxValue)
888 throw new OverflowException ();
890 return new ShortConstant ((short) Value, Location);
892 if (target_type == TypeManager.int32_type)
893 return new IntConstant ((int) Value, Location);
894 if (target_type == TypeManager.uint32_type)
895 return new UIntConstant ((uint) Value, Location);
896 if (target_type == TypeManager.int64_type)
897 return new LongConstant ((long) Value, Location);
898 if (target_type == TypeManager.uint64_type)
899 return new ULongConstant ((ulong) Value, Location);
900 if (target_type == TypeManager.float_type)
901 return new FloatConstant ((float) Value, Location);
902 if (target_type == TypeManager.double_type)
903 return new DoubleConstant ((double) Value, Location);
904 if (target_type == TypeManager.char_type) {
905 if (in_checked_context){
906 if (Value > Char.MaxValue)
907 throw new OverflowException ();
909 return new CharConstant ((char) Value, Location);
911 if (target_type == TypeManager.decimal_type)
912 return new DecimalConstant ((decimal) Value, Location);
914 return null;
918 public class IntConstant : IntegralConstant {
919 public readonly int Value;
921 public IntConstant (int v, Location loc):
922 base (loc)
924 Value = v;
927 protected override Expression DoResolve (ResolveContext rc)
929 type = TypeManager.int32_type;
930 eclass = ExprClass.Value;
931 return this;
934 static public void EmitInt (ILGenerator ig, int i)
936 switch (i){
937 case -1:
938 ig.Emit (OpCodes.Ldc_I4_M1);
939 break;
941 case 0:
942 ig.Emit (OpCodes.Ldc_I4_0);
943 break;
945 case 1:
946 ig.Emit (OpCodes.Ldc_I4_1);
947 break;
949 case 2:
950 ig.Emit (OpCodes.Ldc_I4_2);
951 break;
953 case 3:
954 ig.Emit (OpCodes.Ldc_I4_3);
955 break;
957 case 4:
958 ig.Emit (OpCodes.Ldc_I4_4);
959 break;
961 case 5:
962 ig.Emit (OpCodes.Ldc_I4_5);
963 break;
965 case 6:
966 ig.Emit (OpCodes.Ldc_I4_6);
967 break;
969 case 7:
970 ig.Emit (OpCodes.Ldc_I4_7);
971 break;
973 case 8:
974 ig.Emit (OpCodes.Ldc_I4_8);
975 break;
977 default:
978 if (i >= -128 && i <= 127){
979 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
980 } else
981 ig.Emit (OpCodes.Ldc_I4, i);
982 break;
986 public override void Emit (EmitContext ec)
988 EmitInt (ec.ig, Value);
991 public override string AsString ()
993 return Value.ToString ();
996 public override object GetValue ()
998 return Value;
1001 public override Constant Increment ()
1003 return new IntConstant (checked(Value + 1), loc);
1006 public override bool IsDefaultValue {
1007 get {
1008 return Value == 0;
1012 public override bool IsNegative {
1013 get {
1014 return Value < 0;
1018 public override bool IsOneInteger {
1019 get {
1020 return Value == 1;
1024 public override bool IsZeroInteger {
1025 get { return Value == 0; }
1028 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1030 if (target_type == TypeManager.byte_type) {
1031 if (in_checked_context){
1032 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1033 throw new OverflowException ();
1035 return new ByteConstant ((byte) Value, Location);
1037 if (target_type == TypeManager.sbyte_type) {
1038 if (in_checked_context){
1039 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1040 throw new OverflowException ();
1042 return new SByteConstant ((sbyte) Value, Location);
1044 if (target_type == TypeManager.short_type) {
1045 if (in_checked_context){
1046 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1047 throw new OverflowException ();
1049 return new ShortConstant ((short) Value, Location);
1051 if (target_type == TypeManager.ushort_type) {
1052 if (in_checked_context){
1053 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1054 throw new OverflowException ();
1056 return new UShortConstant ((ushort) Value, Location);
1058 if (target_type == TypeManager.uint32_type) {
1059 if (in_checked_context){
1060 if (Value < UInt32.MinValue)
1061 throw new OverflowException ();
1063 return new UIntConstant ((uint) Value, Location);
1065 if (target_type == TypeManager.int64_type)
1066 return new LongConstant ((long) Value, Location);
1067 if (target_type == TypeManager.uint64_type) {
1068 if (in_checked_context && Value < 0)
1069 throw new OverflowException ();
1070 return new ULongConstant ((ulong) Value, Location);
1072 if (target_type == TypeManager.float_type)
1073 return new FloatConstant ((float) Value, Location);
1074 if (target_type == TypeManager.double_type)
1075 return new DoubleConstant ((double) Value, Location);
1076 if (target_type == TypeManager.char_type) {
1077 if (in_checked_context){
1078 if (Value < Char.MinValue || Value > Char.MaxValue)
1079 throw new OverflowException ();
1081 return new CharConstant ((char) Value, Location);
1083 if (target_type == TypeManager.decimal_type)
1084 return new DecimalConstant ((decimal) Value, Location);
1086 return null;
1089 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
1091 if (this.type == type)
1092 return this;
1094 Constant c = TryImplicitIntConversion (type);
1095 if (c != null)
1096 return c.Resolve (rc);
1098 return base.ConvertImplicitly (rc, type);
1101 /// <summary>
1102 /// Attempts to perform an implicit constant conversion of the IntConstant
1103 /// into a different data type using casts (See Implicit Constant
1104 /// Expression Conversions)
1105 /// </summary>
1106 Constant TryImplicitIntConversion (Type target_type)
1108 if (target_type == TypeManager.sbyte_type) {
1109 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1110 return new SByteConstant ((sbyte) Value, loc);
1112 else if (target_type == TypeManager.byte_type) {
1113 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1114 return new ByteConstant ((byte) Value, loc);
1116 else if (target_type == TypeManager.short_type) {
1117 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1118 return new ShortConstant ((short) Value, loc);
1120 else if (target_type == TypeManager.ushort_type) {
1121 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1122 return new UShortConstant ((ushort) Value, loc);
1124 else if (target_type == TypeManager.uint32_type) {
1125 if (Value >= 0)
1126 return new UIntConstant ((uint) Value, loc);
1128 else if (target_type == TypeManager.uint64_type) {
1130 // we can optimize this case: a positive int32
1131 // always fits on a uint64. But we need an opcode
1132 // to do it.
1134 if (Value >= 0)
1135 return new ULongConstant ((ulong) Value, loc);
1137 else if (target_type == TypeManager.double_type)
1138 return new DoubleConstant ((double) Value, loc);
1139 else if (target_type == TypeManager.float_type)
1140 return new FloatConstant ((float) Value, loc);
1142 return null;
1146 public class UIntConstant : IntegralConstant {
1147 public readonly uint Value;
1149 public UIntConstant (uint v, Location loc):
1150 base (loc)
1152 Value = v;
1155 protected override Expression DoResolve (ResolveContext rc)
1157 type = TypeManager.uint32_type;
1158 eclass = ExprClass.Value;
1159 return this;
1162 public override void Emit (EmitContext ec)
1164 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1167 public override string AsString ()
1169 return Value.ToString ();
1172 public override object GetValue ()
1174 return Value;
1177 public override Constant Increment ()
1179 return new UIntConstant (checked(Value + 1), loc);
1182 public override bool IsDefaultValue {
1183 get {
1184 return Value == 0;
1188 public override bool IsNegative {
1189 get {
1190 return false;
1194 public override bool IsOneInteger {
1195 get {
1196 return Value == 1;
1200 public override bool IsZeroInteger {
1201 get { return Value == 0; }
1204 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1206 if (target_type == TypeManager.byte_type) {
1207 if (in_checked_context){
1208 if (Value < Char.MinValue || Value > Char.MaxValue)
1209 throw new OverflowException ();
1211 return new ByteConstant ((byte) Value, Location);
1213 if (target_type == TypeManager.sbyte_type) {
1214 if (in_checked_context){
1215 if (Value > SByte.MaxValue)
1216 throw new OverflowException ();
1218 return new SByteConstant ((sbyte) Value, Location);
1220 if (target_type == TypeManager.short_type) {
1221 if (in_checked_context){
1222 if (Value > Int16.MaxValue)
1223 throw new OverflowException ();
1225 return new ShortConstant ((short) Value, Location);
1227 if (target_type == TypeManager.ushort_type) {
1228 if (in_checked_context){
1229 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1230 throw new OverflowException ();
1232 return new UShortConstant ((ushort) Value, Location);
1234 if (target_type == TypeManager.int32_type) {
1235 if (in_checked_context){
1236 if (Value > Int32.MaxValue)
1237 throw new OverflowException ();
1239 return new IntConstant ((int) Value, Location);
1241 if (target_type == TypeManager.int64_type)
1242 return new LongConstant ((long) Value, Location);
1243 if (target_type == TypeManager.uint64_type)
1244 return new ULongConstant ((ulong) Value, Location);
1245 if (target_type == TypeManager.float_type)
1246 return new FloatConstant ((float) Value, Location);
1247 if (target_type == TypeManager.double_type)
1248 return new DoubleConstant ((double) Value, Location);
1249 if (target_type == TypeManager.char_type) {
1250 if (in_checked_context){
1251 if (Value < Char.MinValue || Value > Char.MaxValue)
1252 throw new OverflowException ();
1254 return new CharConstant ((char) Value, Location);
1256 if (target_type == TypeManager.decimal_type)
1257 return new DecimalConstant ((decimal) Value, Location);
1259 return null;
1264 public class LongConstant : IntegralConstant {
1265 public readonly long Value;
1267 public LongConstant (long v, Location loc):
1268 base (loc)
1270 Value = v;
1273 protected override Expression DoResolve (ResolveContext rc)
1275 type = TypeManager.int64_type;
1276 eclass = ExprClass.Value;
1277 return this;
1280 public override void Emit (EmitContext ec)
1282 EmitLong (ec.ig, Value);
1285 static public void EmitLong (ILGenerator ig, long l)
1287 if (l >= int.MinValue && l <= int.MaxValue) {
1288 IntLiteral.EmitInt (ig, unchecked ((int) l));
1289 ig.Emit (OpCodes.Conv_I8);
1290 return;
1293 if (l >= 0 && l <= uint.MaxValue) {
1294 IntLiteral.EmitInt (ig, unchecked ((int) l));
1295 ig.Emit (OpCodes.Conv_U8);
1296 return;
1299 ig.Emit (OpCodes.Ldc_I8, l);
1302 public override string AsString ()
1304 return Value.ToString ();
1307 public override object GetValue ()
1309 return Value;
1312 public override Constant Increment ()
1314 return new LongConstant (checked(Value + 1), loc);
1317 public override bool IsDefaultValue {
1318 get {
1319 return Value == 0;
1323 public override bool IsNegative {
1324 get {
1325 return Value < 0;
1329 public override bool IsOneInteger {
1330 get {
1331 return Value == 1;
1335 public override bool IsZeroInteger {
1336 get { return Value == 0; }
1339 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1341 if (target_type == TypeManager.byte_type) {
1342 if (in_checked_context){
1343 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1344 throw new OverflowException ();
1346 return new ByteConstant ((byte) Value, Location);
1348 if (target_type == TypeManager.sbyte_type) {
1349 if (in_checked_context){
1350 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1351 throw new OverflowException ();
1353 return new SByteConstant ((sbyte) Value, Location);
1355 if (target_type == TypeManager.short_type) {
1356 if (in_checked_context){
1357 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1358 throw new OverflowException ();
1360 return new ShortConstant ((short) Value, Location);
1362 if (target_type == TypeManager.ushort_type) {
1363 if (in_checked_context){
1364 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1365 throw new OverflowException ();
1367 return new UShortConstant ((ushort) Value, Location);
1369 if (target_type == TypeManager.int32_type) {
1370 if (in_checked_context){
1371 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1372 throw new OverflowException ();
1374 return new IntConstant ((int) Value, Location);
1376 if (target_type == TypeManager.uint32_type) {
1377 if (in_checked_context){
1378 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1379 throw new OverflowException ();
1381 return new UIntConstant ((uint) Value, Location);
1383 if (target_type == TypeManager.uint64_type) {
1384 if (in_checked_context && Value < 0)
1385 throw new OverflowException ();
1386 return new ULongConstant ((ulong) Value, Location);
1388 if (target_type == TypeManager.float_type)
1389 return new FloatConstant ((float) Value, Location);
1390 if (target_type == TypeManager.double_type)
1391 return new DoubleConstant ((double) Value, Location);
1392 if (target_type == TypeManager.char_type) {
1393 if (in_checked_context){
1394 if (Value < Char.MinValue || Value > Char.MaxValue)
1395 throw new OverflowException ();
1397 return new CharConstant ((char) Value, Location);
1399 if (target_type == TypeManager.decimal_type)
1400 return new DecimalConstant ((decimal) Value, Location);
1402 return null;
1405 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
1407 if (Value >= 0 && type == TypeManager.uint64_type) {
1408 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1411 return base.ConvertImplicitly (rc, type);
1415 public class ULongConstant : IntegralConstant {
1416 public readonly ulong Value;
1418 public ULongConstant (ulong v, Location loc):
1419 base (loc)
1421 Value = v;
1424 protected override Expression DoResolve (ResolveContext rc)
1426 type = TypeManager.uint64_type;
1427 eclass = ExprClass.Value;
1428 return this;
1431 public override void Emit (EmitContext ec)
1433 ILGenerator ig = ec.ig;
1435 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1438 public override string AsString ()
1440 return Value.ToString ();
1443 public override object GetValue ()
1445 return Value;
1448 public override Constant Increment ()
1450 return new ULongConstant (checked(Value + 1), loc);
1453 public override bool IsDefaultValue {
1454 get {
1455 return Value == 0;
1459 public override bool IsNegative {
1460 get {
1461 return false;
1465 public override bool IsOneInteger {
1466 get {
1467 return Value == 1;
1471 public override bool IsZeroInteger {
1472 get { return Value == 0; }
1475 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1477 if (target_type == TypeManager.byte_type) {
1478 if (in_checked_context && Value > Byte.MaxValue)
1479 throw new OverflowException ();
1480 return new ByteConstant ((byte) Value, Location);
1482 if (target_type == TypeManager.sbyte_type) {
1483 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1484 throw new OverflowException ();
1485 return new SByteConstant ((sbyte) Value, Location);
1487 if (target_type == TypeManager.short_type) {
1488 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1489 throw new OverflowException ();
1490 return new ShortConstant ((short) Value, Location);
1492 if (target_type == TypeManager.ushort_type) {
1493 if (in_checked_context && Value > UInt16.MaxValue)
1494 throw new OverflowException ();
1495 return new UShortConstant ((ushort) Value, Location);
1497 if (target_type == TypeManager.int32_type) {
1498 if (in_checked_context && Value > UInt32.MaxValue)
1499 throw new OverflowException ();
1500 return new IntConstant ((int) Value, Location);
1502 if (target_type == TypeManager.uint32_type) {
1503 if (in_checked_context && Value > UInt32.MaxValue)
1504 throw new OverflowException ();
1505 return new UIntConstant ((uint) Value, Location);
1507 if (target_type == TypeManager.int64_type) {
1508 if (in_checked_context && Value > Int64.MaxValue)
1509 throw new OverflowException ();
1510 return new LongConstant ((long) Value, Location);
1512 if (target_type == TypeManager.float_type)
1513 return new FloatConstant ((float) Value, Location);
1514 if (target_type == TypeManager.double_type)
1515 return new DoubleConstant ((double) Value, Location);
1516 if (target_type == TypeManager.char_type) {
1517 if (in_checked_context && Value > Char.MaxValue)
1518 throw new OverflowException ();
1519 return new CharConstant ((char) Value, Location);
1521 if (target_type == TypeManager.decimal_type)
1522 return new DecimalConstant ((decimal) Value, Location);
1524 return null;
1529 public class FloatConstant : Constant {
1530 public float Value;
1532 public FloatConstant (float v, Location loc):
1533 base (loc)
1535 Value = v;
1538 protected override Expression DoResolve (ResolveContext rc)
1540 type = TypeManager.float_type;
1541 eclass = ExprClass.Value;
1542 return this;
1545 public override void Emit (EmitContext ec)
1547 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1550 public override string AsString ()
1552 return Value.ToString ();
1555 public override object GetValue ()
1557 return Value;
1560 public override bool IsDefaultValue {
1561 get {
1562 return Value == 0;
1566 public override bool IsNegative {
1567 get {
1568 return Value < 0;
1572 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1574 if (target_type == TypeManager.byte_type) {
1575 if (in_checked_context){
1576 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1577 throw new OverflowException ();
1579 return new ByteConstant ((byte) Value, Location);
1581 if (target_type == TypeManager.sbyte_type) {
1582 if (in_checked_context){
1583 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1584 throw new OverflowException ();
1586 return new SByteConstant ((sbyte) Value, Location);
1588 if (target_type == TypeManager.short_type) {
1589 if (in_checked_context){
1590 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1591 throw new OverflowException ();
1593 return new ShortConstant ((short) Value, Location);
1595 if (target_type == TypeManager.ushort_type) {
1596 if (in_checked_context){
1597 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1598 throw new OverflowException ();
1600 return new UShortConstant ((ushort) Value, Location);
1602 if (target_type == TypeManager.int32_type) {
1603 if (in_checked_context){
1604 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1605 throw new OverflowException ();
1607 return new IntConstant ((int) Value, Location);
1609 if (target_type == TypeManager.uint32_type) {
1610 if (in_checked_context){
1611 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1612 throw new OverflowException ();
1614 return new UIntConstant ((uint) Value, Location);
1616 if (target_type == TypeManager.int64_type) {
1617 if (in_checked_context){
1618 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1619 throw new OverflowException ();
1621 return new LongConstant ((long) Value, Location);
1623 if (target_type == TypeManager.uint64_type) {
1624 if (in_checked_context){
1625 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1626 throw new OverflowException ();
1628 return new ULongConstant ((ulong) Value, Location);
1630 if (target_type == TypeManager.double_type)
1631 return new DoubleConstant ((double) Value, Location);
1632 if (target_type == TypeManager.char_type) {
1633 if (in_checked_context){
1634 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1635 throw new OverflowException ();
1637 return new CharConstant ((char) Value, Location);
1639 if (target_type == TypeManager.decimal_type)
1640 return new DecimalConstant ((decimal) Value, Location);
1642 return null;
1647 public class DoubleConstant : Constant {
1648 public double Value;
1650 public DoubleConstant (double v, Location loc):
1651 base (loc)
1653 Value = v;
1656 protected override Expression DoResolve (ResolveContext rc)
1658 type = TypeManager.double_type;
1659 eclass = ExprClass.Value;
1660 return this;
1663 public override void Emit (EmitContext ec)
1665 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1668 public override string AsString ()
1670 return Value.ToString ();
1673 public override object GetValue ()
1675 return Value;
1678 public override bool IsDefaultValue {
1679 get {
1680 return Value == 0;
1684 public override bool IsNegative {
1685 get {
1686 return Value < 0;
1690 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1692 if (target_type == TypeManager.byte_type) {
1693 if (in_checked_context){
1694 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1695 throw new OverflowException ();
1697 return new ByteConstant ((byte) Value, Location);
1699 if (target_type == TypeManager.sbyte_type) {
1700 if (in_checked_context){
1701 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1702 throw new OverflowException ();
1704 return new SByteConstant ((sbyte) Value, Location);
1706 if (target_type == TypeManager.short_type) {
1707 if (in_checked_context){
1708 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1709 throw new OverflowException ();
1711 return new ShortConstant ((short) Value, Location);
1713 if (target_type == TypeManager.ushort_type) {
1714 if (in_checked_context){
1715 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1716 throw new OverflowException ();
1718 return new UShortConstant ((ushort) Value, Location);
1720 if (target_type == TypeManager.int32_type) {
1721 if (in_checked_context){
1722 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1723 throw new OverflowException ();
1725 return new IntConstant ((int) Value, Location);
1727 if (target_type == TypeManager.uint32_type) {
1728 if (in_checked_context){
1729 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1730 throw new OverflowException ();
1732 return new UIntConstant ((uint) Value, Location);
1734 if (target_type == TypeManager.int64_type) {
1735 if (in_checked_context){
1736 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1737 throw new OverflowException ();
1739 return new LongConstant ((long) Value, Location);
1741 if (target_type == TypeManager.uint64_type) {
1742 if (in_checked_context){
1743 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1744 throw new OverflowException ();
1746 return new ULongConstant ((ulong) Value, Location);
1748 if (target_type == TypeManager.float_type)
1749 return new FloatConstant ((float) Value, Location);
1750 if (target_type == TypeManager.char_type) {
1751 if (in_checked_context){
1752 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1753 throw new OverflowException ();
1755 return new CharConstant ((char) Value, Location);
1757 if (target_type == TypeManager.decimal_type)
1758 return new DecimalConstant ((decimal) Value, Location);
1760 return null;
1765 public class DecimalConstant : Constant {
1766 public readonly decimal Value;
1768 public DecimalConstant (decimal d, Location loc):
1769 base (loc)
1771 Value = d;
1774 override public string AsString ()
1776 return Value.ToString () + "M";
1779 protected override Expression DoResolve (ResolveContext rc)
1781 type = TypeManager.decimal_type;
1782 eclass = ExprClass.Value;
1783 return this;
1786 public override object GetValue ()
1788 return (object) Value;
1791 public override void Emit (EmitContext ec)
1793 ILGenerator ig = ec.ig;
1795 int [] words = decimal.GetBits (Value);
1796 int power = (words [3] >> 16) & 0xff;
1798 if (power == 0) {
1799 if (Value <= int.MaxValue && Value >= int.MinValue) {
1800 if (TypeManager.void_decimal_ctor_int_arg == null) {
1801 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1802 TypeManager.decimal_type, loc, TypeManager.int32_type);
1804 if (TypeManager.void_decimal_ctor_int_arg == null)
1805 return;
1808 IntConstant.EmitInt (ig, (int) Value);
1809 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1810 return;
1813 if (Value <= long.MaxValue && Value >= long.MinValue) {
1814 if (TypeManager.void_decimal_ctor_long_arg == null) {
1815 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1816 TypeManager.decimal_type, loc, TypeManager.int64_type);
1818 if (TypeManager.void_decimal_ctor_long_arg == null)
1819 return;
1822 LongConstant.EmitLong (ig, (long) Value);
1823 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1824 return;
1828 IntConstant.EmitInt (ig, words [0]);
1829 IntConstant.EmitInt (ig, words [1]);
1830 IntConstant.EmitInt (ig, words [2]);
1832 // sign
1833 IntConstant.EmitInt (ig, words [3] >> 31);
1835 // power
1836 IntConstant.EmitInt (ig, power);
1838 if (TypeManager.void_decimal_ctor_five_args == null) {
1839 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1840 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1841 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1843 if (TypeManager.void_decimal_ctor_five_args == null)
1844 return;
1847 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1850 public override bool IsDefaultValue {
1851 get {
1852 return Value == 0;
1856 public override bool IsNegative {
1857 get {
1858 return Value < 0;
1862 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1864 if (target_type == TypeManager.sbyte_type)
1865 return new SByteConstant ((sbyte)Value, loc);
1866 if (target_type == TypeManager.byte_type)
1867 return new ByteConstant ((byte)Value, loc);
1868 if (target_type == TypeManager.short_type)
1869 return new ShortConstant ((short)Value, loc);
1870 if (target_type == TypeManager.ushort_type)
1871 return new UShortConstant ((ushort)Value, loc);
1872 if (target_type == TypeManager.int32_type)
1873 return new IntConstant ((int)Value, loc);
1874 if (target_type == TypeManager.uint32_type)
1875 return new UIntConstant ((uint)Value, loc);
1876 if (target_type == TypeManager.int64_type)
1877 return new LongConstant ((long)Value, loc);
1878 if (target_type == TypeManager.uint64_type)
1879 return new ULongConstant ((ulong)Value, loc);
1880 if (target_type == TypeManager.char_type)
1881 return new CharConstant ((char)Value, loc);
1882 if (target_type == TypeManager.float_type)
1883 return new FloatConstant ((float)Value, loc);
1884 if (target_type == TypeManager.double_type)
1885 return new DoubleConstant ((double)Value, loc);
1887 return null;
1892 public class StringConstant : Constant {
1893 public readonly string Value;
1895 public StringConstant (string s, Location loc):
1896 base (loc)
1898 Value = s;
1901 // FIXME: Escape the string.
1902 override public string AsString ()
1904 return "\"" + Value + "\"";
1907 protected override Expression DoResolve (ResolveContext rc)
1909 type = TypeManager.string_type;
1910 eclass = ExprClass.Value;
1911 return this;
1914 public override object GetValue ()
1916 return Value;
1919 public override void Emit (EmitContext ec)
1921 if (Value == null) {
1922 ec.ig.Emit (OpCodes.Ldnull);
1923 return;
1927 // Use string.Empty for both literals and constants even if
1928 // it's not allowed at language level
1930 if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) {
1931 if (TypeManager.string_empty == null)
1932 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
1934 if (TypeManager.string_empty != null) {
1935 ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1936 return;
1940 ec.ig.Emit (OpCodes.Ldstr, Value);
1943 public override bool IsDefaultValue {
1944 get {
1945 return Value == null;
1949 public override bool IsNegative {
1950 get {
1951 return false;
1955 public override bool IsNull {
1956 get {
1957 return IsDefaultValue;
1961 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1963 return null;
1968 // Null constant can have its own type, think of `default (Foo)'
1970 public class NullConstant : Constant
1972 public NullConstant (Type type, Location loc)
1973 : base (loc)
1975 eclass = ExprClass.Value;
1976 this.type = type;
1979 public override string AsString ()
1981 return GetSignatureForError ();
1984 protected override Expression DoResolve (ResolveContext ec)
1986 return this;
1989 public override void Emit (EmitContext ec)
1991 ec.ig.Emit (OpCodes.Ldnull);
1993 // Only to make verifier happy
1994 if (TypeManager.IsGenericParameter (type))
1995 ec.ig.Emit (OpCodes.Unbox_Any, type);
1998 public override string ExprClassName {
1999 get {
2000 return GetSignatureForError ();
2004 public override string GetSignatureForError ()
2006 return "null";
2009 public override Constant ConvertExplicitly (bool inCheckedContext, Type targetType)
2011 if (targetType.IsPointer) {
2012 if (IsLiteral || this is NullPointer)
2013 return new EmptyConstantCast (new NullPointer (loc), targetType);
2015 return null;
2018 // Exlude internal compiler types
2019 if (targetType == InternalType.AnonymousMethod)
2020 return null;
2022 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2023 return null;
2025 if (TypeManager.IsReferenceType (targetType))
2026 return new NullConstant (targetType, loc);
2028 if (TypeManager.IsNullableType (targetType))
2029 return Nullable.LiftedNull.Create (targetType, loc);
2031 return null;
2034 public override Constant ConvertImplicitly (ResolveContext rc, Type targetType)
2036 return ConvertExplicitly (false, targetType);
2039 public override object GetValue ()
2041 return null;
2044 public override bool IsDefaultValue {
2045 get { return true; }
2048 public override bool IsNegative {
2049 get { return false; }
2052 public override bool IsNull {
2053 get { return true; }
2056 public override bool IsZeroInteger {
2057 get { return true; }
2060 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2062 type = storey.MutateType (type);
2066 /// <summary>
2067 /// The value is constant, but when emitted has a side effect. This is
2068 /// used by BitwiseAnd to ensure that the second expression is invoked
2069 /// regardless of the value of the left side.
2070 /// </summary>
2071 public class SideEffectConstant : Constant {
2072 public Constant value;
2073 Expression side_effect;
2075 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2077 this.value = value;
2078 while (side_effect is SideEffectConstant)
2079 side_effect = ((SideEffectConstant) side_effect).side_effect;
2080 this.side_effect = side_effect;
2083 public override string AsString ()
2085 return value.AsString ();
2088 protected override Expression DoResolve (ResolveContext rc)
2090 value = value.Resolve (rc);
2092 type = value.Type;
2093 eclass = ExprClass.Value;
2094 return this;
2097 public override object GetValue ()
2099 return value.GetValue ();
2102 public override void Emit (EmitContext ec)
2104 side_effect.EmitSideEffect (ec);
2105 value.Emit (ec);
2108 public override void EmitSideEffect (EmitContext ec)
2110 side_effect.EmitSideEffect (ec);
2111 value.EmitSideEffect (ec);
2114 public override bool IsDefaultValue {
2115 get { return value.IsDefaultValue; }
2118 public override bool IsNegative {
2119 get { return value.IsNegative; }
2122 public override bool IsZeroInteger {
2123 get { return value.IsZeroInteger; }
2126 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
2128 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2129 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);