2009-11-24 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / constant.cs
blob18c7aacbdc21ca6e18334ff6214b024d5c818c1b
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 namespace Mono.CSharp {
14 using System;
15 using System.Reflection.Emit;
16 using System.Collections;
18 /// <summary>
19 /// Base class for constants and literals.
20 /// </summary>
21 public abstract class Constant : Expression {
23 protected Constant (Location loc)
25 this.loc = loc;
28 /// <remarks>
29 /// This is different from ToString in that ToString
30 /// is supposed to be there for debugging purposes,
31 /// and is not guaranteed to be useful for anything else,
32 /// AsString() will provide something that can be used
33 /// for round-tripping C# code. Maybe it can be used
34 /// for IL assembly as well.
35 /// </remarks>
36 public abstract string AsString ();
38 override public string ToString ()
40 return this.GetType ().Name + " (" + AsString () + ")";
43 public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
45 if (value_type == TypeManager.object_type) {
46 value = GetTypedValue ();
47 return true;
50 Constant c = ImplicitConversionRequired (ec, value_type, loc);
51 if (c == null) {
52 value = null;
53 return false;
56 value = c.GetTypedValue ();
57 return true;
60 /// <summary>
61 /// This is used to obtain the actual value of the literal
62 /// cast into an object.
63 /// </summary>
64 public abstract object GetValue ();
66 public virtual object GetTypedValue ()
68 return GetValue ();
71 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
73 if (!expl && IsLiteral &&
74 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
75 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
76 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
77 AsString (), TypeManager.CSharpName (target));
78 } else {
79 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
83 public Constant ImplicitConversionRequired (ResolveContext ec, Type type, Location loc)
85 Constant c = ConvertImplicitly (ec, type);
86 if (c == null)
87 Error_ValueCannotBeConverted (ec, loc, type, false);
89 return c;
92 public virtual Constant ConvertImplicitly (ResolveContext rc, Type type)
94 if (this.type == type)
95 return this;
97 if (Convert.ImplicitNumericConversion (this, type) == null)
98 return null;
100 bool fail;
101 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
102 if (fail){
104 // We should always catch the error before this is ever
105 // reached, by calling Convert.ImplicitStandardConversionExists
107 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
108 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
111 return CreateConstant (rc, type, constant_value, loc);
115 // Returns a constant instance based on Type
117 public static Constant CreateConstant (ResolveContext rc, Type t, object v, Location loc)
119 return CreateConstantFromValue (t, v, loc).Resolve (rc);
122 public static Constant CreateConstantFromValue (Type t, object v, Location loc)
124 if (t == TypeManager.int32_type)
125 return new IntConstant ((int) v, loc);
126 if (t == TypeManager.string_type)
127 return new StringConstant ((string) v, loc);
128 if (t == TypeManager.uint32_type)
129 return new UIntConstant ((uint) v, loc);
130 if (t == TypeManager.int64_type)
131 return new LongConstant ((long) v, loc);
132 if (t == TypeManager.uint64_type)
133 return new ULongConstant ((ulong) v, loc);
134 if (t == TypeManager.float_type)
135 return new FloatConstant ((float) v, loc);
136 if (t == TypeManager.double_type)
137 return new DoubleConstant ((double) v, loc);
138 if (t == TypeManager.short_type)
139 return new ShortConstant ((short)v, loc);
140 if (t == TypeManager.ushort_type)
141 return new UShortConstant ((ushort)v, loc);
142 if (t == TypeManager.sbyte_type)
143 return new SByteConstant ((sbyte)v, loc);
144 if (t == TypeManager.byte_type)
145 return new ByteConstant ((byte)v, loc);
146 if (t == TypeManager.char_type)
147 return new CharConstant ((char)v, loc);
148 if (t == TypeManager.bool_type)
149 return new BoolConstant ((bool) v, loc);
150 if (t == TypeManager.decimal_type)
151 return new DecimalConstant ((decimal) v, loc);
152 if (TypeManager.IsEnumType (t)) {
153 Type real_type = TypeManager.GetEnumUnderlyingType (t);
154 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
156 if (v == null) {
157 if (TypeManager.IsNullableType (t))
158 return Nullable.LiftedNull.Create (t, loc);
160 if (TypeManager.IsReferenceType (t))
161 return new NullConstant (t, loc);
164 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
165 v, TypeManager.CSharpName (t));
168 public override Expression CreateExpressionTree (ResolveContext ec)
170 Arguments args = new Arguments (2);
171 args.Add (new Argument (this));
172 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
174 return CreateExpressionFactoryCall (ec, "Constant", args);
178 /// <summary>
179 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
180 /// It throws OverflowException
181 /// </summary>
182 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
183 public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type);
185 /// <summary>
186 /// Attempts to do a compile-time folding of a constant cast.
187 /// </summary>
188 public Constant TryReduce (ResolveContext ec, Type target_type, Location loc)
190 try {
191 return TryReduce (ec, target_type);
193 catch (OverflowException) {
194 if (ec.ConstantCheckState) {
195 ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
196 GetValue ().ToString (), TypeManager.CSharpName (target_type));
197 } else {
198 Error_ValueCannotBeConverted (ec, loc, target_type, false);
201 return New.Constantify (target_type).Resolve (ec);
205 Constant TryReduce (ResolveContext ec, Type target_type)
207 if (Type == target_type)
208 return this;
210 Constant c;
211 if (TypeManager.IsEnumType (target_type)) {
212 c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type));
213 if (c == null)
214 return null;
216 return new EnumConstant (c, target_type).Resolve (ec);
219 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
220 if (c != null)
221 c = c.Resolve (ec);
223 return c;
226 /// <summary>
227 /// Need to pass type as the constant can require a boxing
228 /// and in such case no optimization is possible
229 /// </summary>
230 public bool IsDefaultInitializer (Type type)
232 if (type == Type)
233 return IsDefaultValue;
235 return this is NullLiteral;
238 public abstract bool IsDefaultValue {
239 get;
242 public abstract bool IsNegative {
243 get;
247 // When constant is declared as literal
249 public virtual bool IsLiteral {
250 get { return false; }
254 // Returns true iff 1) the stack type of this is one of Object,
255 // int32, int64 and 2) this == 0 or this == null.
257 public virtual bool IsZeroInteger {
258 get { return false; }
261 public override void EmitSideEffect (EmitContext ec)
263 // do nothing
266 protected override void CloneTo (CloneContext clonectx, Expression target)
268 // CloneTo: Nothing, we do not keep any state on this expression
271 #if NET_4_0
272 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
274 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type);
276 #endif
278 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
280 // A constant cannot be of generic type
283 public new Constant Resolve (ResolveContext rc)
285 if (eclass != ExprClass.Unresolved)
286 return this;
288 // Resolved constant has to be still a constant
289 Constant c = (Constant) DoResolve (rc);
290 if (c == null)
291 return null;
293 if ((c.eclass & ExprClass.Value) == 0) {
294 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
295 return null;
298 if (c.type == null)
299 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
301 return c;
305 public abstract class IntegralConstant : Constant {
306 protected IntegralConstant (Location loc) :
307 base (loc)
311 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
313 try {
314 ConvertExplicitly (true, target);
315 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
317 catch
319 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
320 GetValue ().ToString (), TypeManager.CSharpName (target));
324 public abstract Constant Increment ();
327 public class BoolConstant : Constant {
328 public readonly bool Value;
330 public BoolConstant (bool val, Location loc):
331 base (loc)
333 Value = val;
336 override public string AsString ()
338 return Value ? "true" : "false";
341 protected override Expression DoResolve (ResolveContext ec)
343 type = TypeManager.bool_type;
344 eclass = ExprClass.Value;
345 return this;
348 public override object GetValue ()
350 return (object) Value;
353 public override void Emit (EmitContext ec)
355 if (Value)
356 ec.ig.Emit (OpCodes.Ldc_I4_1);
357 else
358 ec.ig.Emit (OpCodes.Ldc_I4_0);
361 public override bool IsDefaultValue {
362 get {
363 return !Value;
367 public override bool IsNegative {
368 get {
369 return false;
373 public override bool IsZeroInteger {
374 get { return Value == false; }
377 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
379 return null;
384 public class ByteConstant : IntegralConstant {
385 public readonly byte Value;
387 public ByteConstant (byte v, Location loc):
388 base (loc)
390 Value = v;
393 public override void Emit (EmitContext ec)
395 IntLiteral.EmitInt (ec.ig, Value);
398 public override string AsString ()
400 return Value.ToString ();
403 protected override Expression DoResolve (ResolveContext ec)
405 type = TypeManager.byte_type;
406 eclass = ExprClass.Value;
407 return this;
410 public override object GetValue ()
412 return Value;
415 public override Constant Increment ()
417 return new ByteConstant (checked ((byte)(Value + 1)), loc);
420 public override bool IsDefaultValue {
421 get {
422 return Value == 0;
426 public override bool IsNegative {
427 get {
428 return false;
432 public override bool IsZeroInteger {
433 get { return Value == 0; }
436 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
438 if (target_type == TypeManager.sbyte_type) {
439 if (in_checked_context){
440 if (Value > SByte.MaxValue)
441 throw new OverflowException ();
443 return new SByteConstant ((sbyte) Value, Location);
445 if (target_type == TypeManager.short_type)
446 return new ShortConstant ((short) Value, Location);
447 if (target_type == TypeManager.ushort_type)
448 return new UShortConstant ((ushort) Value, Location);
449 if (target_type == TypeManager.int32_type)
450 return new IntConstant ((int) Value, Location);
451 if (target_type == TypeManager.uint32_type)
452 return new UIntConstant ((uint) Value, Location);
453 if (target_type == TypeManager.int64_type)
454 return new LongConstant ((long) Value, Location);
455 if (target_type == TypeManager.uint64_type)
456 return new ULongConstant ((ulong) Value, Location);
457 if (target_type == TypeManager.float_type)
458 return new FloatConstant ((float) Value, Location);
459 if (target_type == TypeManager.double_type)
460 return new DoubleConstant ((double) Value, Location);
461 if (target_type == TypeManager.char_type)
462 return new CharConstant ((char) Value, Location);
463 if (target_type == TypeManager.decimal_type)
464 return new DecimalConstant ((decimal) Value, Location);
466 return null;
471 public class CharConstant : Constant {
472 public readonly char Value;
474 public CharConstant (char v, Location loc):
475 base (loc)
477 Value = v;
480 protected override Expression DoResolve (ResolveContext rc)
482 type = TypeManager.char_type;
483 eclass = ExprClass.Value;
484 return this;
487 public override void Emit (EmitContext ec)
489 IntLiteral.EmitInt (ec.ig, Value);
492 static string descape (char c)
494 switch (c){
495 case '\a':
496 return "\\a";
497 case '\b':
498 return "\\b";
499 case '\n':
500 return "\\n";
501 case '\t':
502 return "\\t";
503 case '\v':
504 return "\\v";
505 case '\r':
506 return "\\r";
507 case '\\':
508 return "\\\\";
509 case '\f':
510 return "\\f";
511 case '\0':
512 return "\\0";
513 case '"':
514 return "\\\"";
515 case '\'':
516 return "\\\'";
518 return c.ToString ();
521 public override string AsString ()
523 return "\"" + descape (Value) + "\"";
526 public override object GetValue ()
528 return Value;
531 public override bool IsDefaultValue {
532 get {
533 return Value == 0;
537 public override bool IsNegative {
538 get {
539 return false;
543 public override bool IsZeroInteger {
544 get { return Value == '\0'; }
547 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
549 if (target_type == TypeManager.byte_type) {
550 if (in_checked_context){
551 if (Value < Byte.MinValue || Value > Byte.MaxValue)
552 throw new OverflowException ();
554 return new ByteConstant ((byte) Value, Location);
556 if (target_type == TypeManager.sbyte_type) {
557 if (in_checked_context){
558 if (Value > SByte.MaxValue)
559 throw new OverflowException ();
561 return new SByteConstant ((sbyte) Value, Location);
563 if (target_type == TypeManager.short_type) {
564 if (in_checked_context){
565 if (Value > Int16.MaxValue)
566 throw new OverflowException ();
568 return new ShortConstant ((short) Value, Location);
570 if (target_type == TypeManager.int32_type)
571 return new IntConstant ((int) Value, Location);
572 if (target_type == TypeManager.uint32_type)
573 return new UIntConstant ((uint) Value, Location);
574 if (target_type == TypeManager.int64_type)
575 return new LongConstant ((long) Value, Location);
576 if (target_type == TypeManager.uint64_type)
577 return new ULongConstant ((ulong) Value, Location);
578 if (target_type == TypeManager.float_type)
579 return new FloatConstant ((float) Value, Location);
580 if (target_type == TypeManager.double_type)
581 return new DoubleConstant ((double) Value, Location);
582 if (target_type == TypeManager.decimal_type)
583 return new DecimalConstant ((decimal) Value, Location);
585 return null;
590 public class SByteConstant : IntegralConstant {
591 public readonly sbyte Value;
593 public SByteConstant (sbyte v, Location loc):
594 base (loc)
596 Value = v;
599 protected override Expression DoResolve (ResolveContext rc)
601 type = TypeManager.sbyte_type;
602 eclass = ExprClass.Value;
603 return this;
606 public override void Emit (EmitContext ec)
608 IntLiteral.EmitInt (ec.ig, Value);
611 public override string AsString ()
613 return Value.ToString ();
616 public override object GetValue ()
618 return Value;
621 public override Constant Increment ()
623 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
626 public override bool IsDefaultValue {
627 get {
628 return Value == 0;
632 public override bool IsNegative {
633 get {
634 return Value < 0;
638 public override bool IsZeroInteger {
639 get { return Value == 0; }
642 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
644 if (target_type == TypeManager.byte_type) {
645 if (in_checked_context && Value < 0)
646 throw new OverflowException ();
647 return new ByteConstant ((byte) Value, Location);
649 if (target_type == TypeManager.short_type)
650 return new ShortConstant ((short) Value, Location);
651 if (target_type == TypeManager.ushort_type) {
652 if (in_checked_context && Value < 0)
653 throw new OverflowException ();
654 return new UShortConstant ((ushort) Value, Location);
655 } if (target_type == TypeManager.int32_type)
656 return new IntConstant ((int) Value, Location);
657 if (target_type == TypeManager.uint32_type) {
658 if (in_checked_context && Value < 0)
659 throw new OverflowException ();
660 return new UIntConstant ((uint) Value, Location);
661 } if (target_type == TypeManager.int64_type)
662 return new LongConstant ((long) Value, Location);
663 if (target_type == TypeManager.uint64_type) {
664 if (in_checked_context && Value < 0)
665 throw new OverflowException ();
666 return new ULongConstant ((ulong) Value, Location);
668 if (target_type == TypeManager.float_type)
669 return new FloatConstant ((float) Value, Location);
670 if (target_type == TypeManager.double_type)
671 return new DoubleConstant ((double) Value, Location);
672 if (target_type == TypeManager.char_type) {
673 if (in_checked_context && Value < 0)
674 throw new OverflowException ();
675 return new CharConstant ((char) Value, Location);
677 if (target_type == TypeManager.decimal_type)
678 return new DecimalConstant ((decimal) Value, Location);
680 return null;
685 public class ShortConstant : IntegralConstant {
686 public readonly short Value;
688 public ShortConstant (short v, Location loc):
689 base (loc)
691 Value = v;
694 protected override Expression DoResolve (ResolveContext rc)
696 type = TypeManager.short_type;
697 eclass = ExprClass.Value;
698 return this;
701 public override void Emit (EmitContext ec)
703 IntLiteral.EmitInt (ec.ig, Value);
706 public override string AsString ()
708 return Value.ToString ();
711 public override object GetValue ()
713 return Value;
716 public override Constant Increment ()
718 return new ShortConstant (checked((short)(Value + 1)), loc);
721 public override bool IsDefaultValue {
722 get {
723 return Value == 0;
727 public override bool IsZeroInteger {
728 get { return Value == 0; }
731 public override bool IsNegative {
732 get {
733 return Value < 0;
737 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
739 if (target_type == TypeManager.byte_type) {
740 if (in_checked_context){
741 if (Value < Byte.MinValue || Value > Byte.MaxValue)
742 throw new OverflowException ();
744 return new ByteConstant ((byte) Value, Location);
746 if (target_type == TypeManager.sbyte_type) {
747 if (in_checked_context){
748 if (Value < SByte.MinValue || Value > SByte.MaxValue)
749 throw new OverflowException ();
751 return new SByteConstant ((sbyte) Value, Location);
753 if (target_type == TypeManager.ushort_type) {
754 if (in_checked_context && Value < 0)
755 throw new OverflowException ();
757 return new UShortConstant ((ushort) Value, Location);
759 if (target_type == TypeManager.int32_type)
760 return new IntConstant ((int) Value, Location);
761 if (target_type == TypeManager.uint32_type) {
762 if (in_checked_context && Value < 0)
763 throw new OverflowException ();
764 return new UIntConstant ((uint) Value, Location);
766 if (target_type == TypeManager.int64_type)
767 return new LongConstant ((long) Value, Location);
768 if (target_type == TypeManager.uint64_type) {
769 if (in_checked_context && Value < 0)
770 throw new OverflowException ();
771 return new ULongConstant ((ulong) Value, Location);
773 if (target_type == TypeManager.float_type)
774 return new FloatConstant ((float) Value, Location);
775 if (target_type == TypeManager.double_type)
776 return new DoubleConstant ((double) Value, Location);
777 if (target_type == TypeManager.char_type) {
778 if (in_checked_context){
779 if (Value < Char.MinValue)
780 throw new OverflowException ();
782 return new CharConstant ((char) Value, Location);
784 if (target_type == TypeManager.decimal_type)
785 return new DecimalConstant ((decimal) Value, Location);
787 return null;
792 public class UShortConstant : IntegralConstant {
793 public readonly ushort Value;
795 public UShortConstant (ushort v, Location loc):
796 base (loc)
798 Value = v;
801 protected override Expression DoResolve (ResolveContext rc)
803 type = TypeManager.ushort_type;
804 eclass = ExprClass.Value;
805 return this;
808 public override void Emit (EmitContext ec)
810 IntLiteral.EmitInt (ec.ig, Value);
813 public override string AsString ()
815 return Value.ToString ();
818 public override object GetValue ()
820 return Value;
823 public override Constant Increment ()
825 return new UShortConstant (checked((ushort)(Value + 1)), loc);
828 public override bool IsDefaultValue {
829 get {
830 return Value == 0;
834 public override bool IsNegative {
835 get {
836 return false;
840 public override bool IsZeroInteger {
841 get { return Value == 0; }
844 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
846 if (target_type == TypeManager.byte_type) {
847 if (in_checked_context){
848 if (Value > Byte.MaxValue)
849 throw new OverflowException ();
851 return new ByteConstant ((byte) Value, Location);
853 if (target_type == TypeManager.sbyte_type) {
854 if (in_checked_context){
855 if (Value > SByte.MaxValue)
856 throw new OverflowException ();
858 return new SByteConstant ((sbyte) Value, Location);
860 if (target_type == TypeManager.short_type) {
861 if (in_checked_context){
862 if (Value > Int16.MaxValue)
863 throw new OverflowException ();
865 return new ShortConstant ((short) Value, Location);
867 if (target_type == TypeManager.int32_type)
868 return new IntConstant ((int) Value, Location);
869 if (target_type == TypeManager.uint32_type)
870 return new UIntConstant ((uint) Value, Location);
871 if (target_type == TypeManager.int64_type)
872 return new LongConstant ((long) Value, Location);
873 if (target_type == TypeManager.uint64_type)
874 return new ULongConstant ((ulong) Value, Location);
875 if (target_type == TypeManager.float_type)
876 return new FloatConstant ((float) Value, Location);
877 if (target_type == TypeManager.double_type)
878 return new DoubleConstant ((double) Value, Location);
879 if (target_type == TypeManager.char_type) {
880 if (in_checked_context){
881 if (Value > Char.MaxValue)
882 throw new OverflowException ();
884 return new CharConstant ((char) Value, Location);
886 if (target_type == TypeManager.decimal_type)
887 return new DecimalConstant ((decimal) Value, Location);
889 return null;
893 public class IntConstant : IntegralConstant {
894 public readonly int Value;
896 public IntConstant (int v, Location loc):
897 base (loc)
899 Value = v;
902 protected override Expression DoResolve (ResolveContext rc)
904 type = TypeManager.int32_type;
905 eclass = ExprClass.Value;
906 return this;
909 static public void EmitInt (ILGenerator ig, int i)
911 switch (i){
912 case -1:
913 ig.Emit (OpCodes.Ldc_I4_M1);
914 break;
916 case 0:
917 ig.Emit (OpCodes.Ldc_I4_0);
918 break;
920 case 1:
921 ig.Emit (OpCodes.Ldc_I4_1);
922 break;
924 case 2:
925 ig.Emit (OpCodes.Ldc_I4_2);
926 break;
928 case 3:
929 ig.Emit (OpCodes.Ldc_I4_3);
930 break;
932 case 4:
933 ig.Emit (OpCodes.Ldc_I4_4);
934 break;
936 case 5:
937 ig.Emit (OpCodes.Ldc_I4_5);
938 break;
940 case 6:
941 ig.Emit (OpCodes.Ldc_I4_6);
942 break;
944 case 7:
945 ig.Emit (OpCodes.Ldc_I4_7);
946 break;
948 case 8:
949 ig.Emit (OpCodes.Ldc_I4_8);
950 break;
952 default:
953 if (i >= -128 && i <= 127){
954 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
955 } else
956 ig.Emit (OpCodes.Ldc_I4, i);
957 break;
961 public override void Emit (EmitContext ec)
963 EmitInt (ec.ig, Value);
966 public override string AsString ()
968 return Value.ToString ();
971 public override object GetValue ()
973 return Value;
976 public override Constant Increment ()
978 return new IntConstant (checked(Value + 1), loc);
981 public override bool IsDefaultValue {
982 get {
983 return Value == 0;
987 public override bool IsNegative {
988 get {
989 return Value < 0;
993 public override bool IsZeroInteger {
994 get { return Value == 0; }
997 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
999 if (target_type == TypeManager.byte_type) {
1000 if (in_checked_context){
1001 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1002 throw new OverflowException ();
1004 return new ByteConstant ((byte) Value, Location);
1006 if (target_type == TypeManager.sbyte_type) {
1007 if (in_checked_context){
1008 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1009 throw new OverflowException ();
1011 return new SByteConstant ((sbyte) Value, Location);
1013 if (target_type == TypeManager.short_type) {
1014 if (in_checked_context){
1015 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1016 throw new OverflowException ();
1018 return new ShortConstant ((short) Value, Location);
1020 if (target_type == TypeManager.ushort_type) {
1021 if (in_checked_context){
1022 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1023 throw new OverflowException ();
1025 return new UShortConstant ((ushort) Value, Location);
1027 if (target_type == TypeManager.uint32_type) {
1028 if (in_checked_context){
1029 if (Value < UInt32.MinValue)
1030 throw new OverflowException ();
1032 return new UIntConstant ((uint) Value, Location);
1034 if (target_type == TypeManager.int64_type)
1035 return new LongConstant ((long) Value, Location);
1036 if (target_type == TypeManager.uint64_type) {
1037 if (in_checked_context && Value < 0)
1038 throw new OverflowException ();
1039 return new ULongConstant ((ulong) Value, Location);
1041 if (target_type == TypeManager.float_type)
1042 return new FloatConstant ((float) Value, Location);
1043 if (target_type == TypeManager.double_type)
1044 return new DoubleConstant ((double) Value, Location);
1045 if (target_type == TypeManager.char_type) {
1046 if (in_checked_context){
1047 if (Value < Char.MinValue || Value > Char.MaxValue)
1048 throw new OverflowException ();
1050 return new CharConstant ((char) Value, Location);
1052 if (target_type == TypeManager.decimal_type)
1053 return new DecimalConstant ((decimal) Value, Location);
1055 return null;
1058 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
1060 if (this.type == type)
1061 return this;
1063 Constant c = TryImplicitIntConversion (type);
1064 if (c != null)
1065 return c.Resolve (rc);
1067 return base.ConvertImplicitly (rc, type);
1070 /// <summary>
1071 /// Attempts to perform an implicit constant conversion of the IntConstant
1072 /// into a different data type using casts (See Implicit Constant
1073 /// Expression Conversions)
1074 /// </summary>
1075 Constant TryImplicitIntConversion (Type target_type)
1077 if (target_type == TypeManager.sbyte_type) {
1078 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1079 return new SByteConstant ((sbyte) Value, loc);
1081 else if (target_type == TypeManager.byte_type) {
1082 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1083 return new ByteConstant ((byte) Value, loc);
1085 else if (target_type == TypeManager.short_type) {
1086 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1087 return new ShortConstant ((short) Value, loc);
1089 else if (target_type == TypeManager.ushort_type) {
1090 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1091 return new UShortConstant ((ushort) Value, loc);
1093 else if (target_type == TypeManager.uint32_type) {
1094 if (Value >= 0)
1095 return new UIntConstant ((uint) Value, loc);
1097 else if (target_type == TypeManager.uint64_type) {
1099 // we can optimize this case: a positive int32
1100 // always fits on a uint64. But we need an opcode
1101 // to do it.
1103 if (Value >= 0)
1104 return new ULongConstant ((ulong) Value, loc);
1106 else if (target_type == TypeManager.double_type)
1107 return new DoubleConstant ((double) Value, loc);
1108 else if (target_type == TypeManager.float_type)
1109 return new FloatConstant ((float) Value, loc);
1111 return null;
1115 public class UIntConstant : IntegralConstant {
1116 public readonly uint Value;
1118 public UIntConstant (uint v, Location loc):
1119 base (loc)
1121 Value = v;
1124 protected override Expression DoResolve (ResolveContext rc)
1126 type = TypeManager.uint32_type;
1127 eclass = ExprClass.Value;
1128 return this;
1131 public override void Emit (EmitContext ec)
1133 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1136 public override string AsString ()
1138 return Value.ToString ();
1141 public override object GetValue ()
1143 return Value;
1146 public override Constant Increment ()
1148 return new UIntConstant (checked(Value + 1), loc);
1151 public override bool IsDefaultValue {
1152 get {
1153 return Value == 0;
1157 public override bool IsNegative {
1158 get {
1159 return false;
1163 public override bool IsZeroInteger {
1164 get { return Value == 0; }
1167 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1169 if (target_type == TypeManager.byte_type) {
1170 if (in_checked_context){
1171 if (Value < Char.MinValue || Value > Char.MaxValue)
1172 throw new OverflowException ();
1174 return new ByteConstant ((byte) Value, Location);
1176 if (target_type == TypeManager.sbyte_type) {
1177 if (in_checked_context){
1178 if (Value > SByte.MaxValue)
1179 throw new OverflowException ();
1181 return new SByteConstant ((sbyte) Value, Location);
1183 if (target_type == TypeManager.short_type) {
1184 if (in_checked_context){
1185 if (Value > Int16.MaxValue)
1186 throw new OverflowException ();
1188 return new ShortConstant ((short) Value, Location);
1190 if (target_type == TypeManager.ushort_type) {
1191 if (in_checked_context){
1192 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1193 throw new OverflowException ();
1195 return new UShortConstant ((ushort) Value, Location);
1197 if (target_type == TypeManager.int32_type) {
1198 if (in_checked_context){
1199 if (Value > Int32.MaxValue)
1200 throw new OverflowException ();
1202 return new IntConstant ((int) Value, Location);
1204 if (target_type == TypeManager.int64_type)
1205 return new LongConstant ((long) Value, Location);
1206 if (target_type == TypeManager.uint64_type)
1207 return new ULongConstant ((ulong) Value, Location);
1208 if (target_type == TypeManager.float_type)
1209 return new FloatConstant ((float) Value, Location);
1210 if (target_type == TypeManager.double_type)
1211 return new DoubleConstant ((double) Value, Location);
1212 if (target_type == TypeManager.char_type) {
1213 if (in_checked_context){
1214 if (Value < Char.MinValue || Value > Char.MaxValue)
1215 throw new OverflowException ();
1217 return new CharConstant ((char) Value, Location);
1219 if (target_type == TypeManager.decimal_type)
1220 return new DecimalConstant ((decimal) Value, Location);
1222 return null;
1227 public class LongConstant : IntegralConstant {
1228 public readonly long Value;
1230 public LongConstant (long v, Location loc):
1231 base (loc)
1233 Value = v;
1236 protected override Expression DoResolve (ResolveContext rc)
1238 type = TypeManager.int64_type;
1239 eclass = ExprClass.Value;
1240 return this;
1243 public override void Emit (EmitContext ec)
1245 EmitLong (ec.ig, Value);
1248 static public void EmitLong (ILGenerator ig, long l)
1250 if (l >= int.MinValue && l <= int.MaxValue) {
1251 IntLiteral.EmitInt (ig, unchecked ((int) l));
1252 ig.Emit (OpCodes.Conv_I8);
1253 return;
1256 if (l >= 0 && l <= uint.MaxValue) {
1257 IntLiteral.EmitInt (ig, unchecked ((int) l));
1258 ig.Emit (OpCodes.Conv_U8);
1259 return;
1262 ig.Emit (OpCodes.Ldc_I8, l);
1265 public override string AsString ()
1267 return Value.ToString ();
1270 public override object GetValue ()
1272 return Value;
1275 public override Constant Increment ()
1277 return new LongConstant (checked(Value + 1), loc);
1280 public override bool IsDefaultValue {
1281 get {
1282 return Value == 0;
1286 public override bool IsNegative {
1287 get {
1288 return Value < 0;
1292 public override bool IsZeroInteger {
1293 get { return Value == 0; }
1296 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1298 if (target_type == TypeManager.byte_type) {
1299 if (in_checked_context){
1300 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1301 throw new OverflowException ();
1303 return new ByteConstant ((byte) Value, Location);
1305 if (target_type == TypeManager.sbyte_type) {
1306 if (in_checked_context){
1307 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1308 throw new OverflowException ();
1310 return new SByteConstant ((sbyte) Value, Location);
1312 if (target_type == TypeManager.short_type) {
1313 if (in_checked_context){
1314 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1315 throw new OverflowException ();
1317 return new ShortConstant ((short) Value, Location);
1319 if (target_type == TypeManager.ushort_type) {
1320 if (in_checked_context){
1321 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1322 throw new OverflowException ();
1324 return new UShortConstant ((ushort) Value, Location);
1326 if (target_type == TypeManager.int32_type) {
1327 if (in_checked_context){
1328 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1329 throw new OverflowException ();
1331 return new IntConstant ((int) Value, Location);
1333 if (target_type == TypeManager.uint32_type) {
1334 if (in_checked_context){
1335 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1336 throw new OverflowException ();
1338 return new UIntConstant ((uint) Value, Location);
1340 if (target_type == TypeManager.uint64_type) {
1341 if (in_checked_context && Value < 0)
1342 throw new OverflowException ();
1343 return new ULongConstant ((ulong) Value, Location);
1345 if (target_type == TypeManager.float_type)
1346 return new FloatConstant ((float) Value, Location);
1347 if (target_type == TypeManager.double_type)
1348 return new DoubleConstant ((double) Value, Location);
1349 if (target_type == TypeManager.char_type) {
1350 if (in_checked_context){
1351 if (Value < Char.MinValue || Value > Char.MaxValue)
1352 throw new OverflowException ();
1354 return new CharConstant ((char) Value, Location);
1356 if (target_type == TypeManager.decimal_type)
1357 return new DecimalConstant ((decimal) Value, Location);
1359 return null;
1362 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
1364 if (Value >= 0 && type == TypeManager.uint64_type) {
1365 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1368 return base.ConvertImplicitly (rc, type);
1372 public class ULongConstant : IntegralConstant {
1373 public readonly ulong Value;
1375 public ULongConstant (ulong v, Location loc):
1376 base (loc)
1378 Value = v;
1381 protected override Expression DoResolve (ResolveContext rc)
1383 type = TypeManager.uint64_type;
1384 eclass = ExprClass.Value;
1385 return this;
1388 public override void Emit (EmitContext ec)
1390 ILGenerator ig = ec.ig;
1392 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1395 public override string AsString ()
1397 return Value.ToString ();
1400 public override object GetValue ()
1402 return Value;
1405 public override Constant Increment ()
1407 return new ULongConstant (checked(Value + 1), loc);
1410 public override bool IsDefaultValue {
1411 get {
1412 return Value == 0;
1416 public override bool IsNegative {
1417 get {
1418 return false;
1422 public override bool IsZeroInteger {
1423 get { return Value == 0; }
1426 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1428 if (target_type == TypeManager.byte_type) {
1429 if (in_checked_context && Value > Byte.MaxValue)
1430 throw new OverflowException ();
1431 return new ByteConstant ((byte) Value, Location);
1433 if (target_type == TypeManager.sbyte_type) {
1434 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1435 throw new OverflowException ();
1436 return new SByteConstant ((sbyte) Value, Location);
1438 if (target_type == TypeManager.short_type) {
1439 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1440 throw new OverflowException ();
1441 return new ShortConstant ((short) Value, Location);
1443 if (target_type == TypeManager.ushort_type) {
1444 if (in_checked_context && Value > UInt16.MaxValue)
1445 throw new OverflowException ();
1446 return new UShortConstant ((ushort) Value, Location);
1448 if (target_type == TypeManager.int32_type) {
1449 if (in_checked_context && Value > UInt32.MaxValue)
1450 throw new OverflowException ();
1451 return new IntConstant ((int) Value, Location);
1453 if (target_type == TypeManager.uint32_type) {
1454 if (in_checked_context && Value > UInt32.MaxValue)
1455 throw new OverflowException ();
1456 return new UIntConstant ((uint) Value, Location);
1458 if (target_type == TypeManager.int64_type) {
1459 if (in_checked_context && Value > Int64.MaxValue)
1460 throw new OverflowException ();
1461 return new LongConstant ((long) Value, Location);
1463 if (target_type == TypeManager.float_type)
1464 return new FloatConstant ((float) Value, Location);
1465 if (target_type == TypeManager.double_type)
1466 return new DoubleConstant ((double) Value, Location);
1467 if (target_type == TypeManager.char_type) {
1468 if (in_checked_context && Value > Char.MaxValue)
1469 throw new OverflowException ();
1470 return new CharConstant ((char) Value, Location);
1472 if (target_type == TypeManager.decimal_type)
1473 return new DecimalConstant ((decimal) Value, Location);
1475 return null;
1480 public class FloatConstant : Constant {
1481 public float Value;
1483 public FloatConstant (float v, Location loc):
1484 base (loc)
1486 Value = v;
1489 protected override Expression DoResolve (ResolveContext rc)
1491 type = TypeManager.float_type;
1492 eclass = ExprClass.Value;
1493 return this;
1496 public override void Emit (EmitContext ec)
1498 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1501 public override string AsString ()
1503 return Value.ToString ();
1506 public override object GetValue ()
1508 return Value;
1511 public override bool IsDefaultValue {
1512 get {
1513 return Value == 0;
1517 public override bool IsNegative {
1518 get {
1519 return Value < 0;
1523 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1525 if (target_type == TypeManager.byte_type) {
1526 if (in_checked_context){
1527 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1528 throw new OverflowException ();
1530 return new ByteConstant ((byte) Value, Location);
1532 if (target_type == TypeManager.sbyte_type) {
1533 if (in_checked_context){
1534 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1535 throw new OverflowException ();
1537 return new SByteConstant ((sbyte) Value, Location);
1539 if (target_type == TypeManager.short_type) {
1540 if (in_checked_context){
1541 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1542 throw new OverflowException ();
1544 return new ShortConstant ((short) Value, Location);
1546 if (target_type == TypeManager.ushort_type) {
1547 if (in_checked_context){
1548 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1549 throw new OverflowException ();
1551 return new UShortConstant ((ushort) Value, Location);
1553 if (target_type == TypeManager.int32_type) {
1554 if (in_checked_context){
1555 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1556 throw new OverflowException ();
1558 return new IntConstant ((int) Value, Location);
1560 if (target_type == TypeManager.uint32_type) {
1561 if (in_checked_context){
1562 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1563 throw new OverflowException ();
1565 return new UIntConstant ((uint) Value, Location);
1567 if (target_type == TypeManager.int64_type) {
1568 if (in_checked_context){
1569 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1570 throw new OverflowException ();
1572 return new LongConstant ((long) Value, Location);
1574 if (target_type == TypeManager.uint64_type) {
1575 if (in_checked_context){
1576 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1577 throw new OverflowException ();
1579 return new ULongConstant ((ulong) Value, Location);
1581 if (target_type == TypeManager.double_type)
1582 return new DoubleConstant ((double) Value, Location);
1583 if (target_type == TypeManager.char_type) {
1584 if (in_checked_context){
1585 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1586 throw new OverflowException ();
1588 return new CharConstant ((char) Value, Location);
1590 if (target_type == TypeManager.decimal_type)
1591 return new DecimalConstant ((decimal) Value, Location);
1593 return null;
1598 public class DoubleConstant : Constant {
1599 public double Value;
1601 public DoubleConstant (double v, Location loc):
1602 base (loc)
1604 Value = v;
1607 protected override Expression DoResolve (ResolveContext rc)
1609 type = TypeManager.double_type;
1610 eclass = ExprClass.Value;
1611 return this;
1614 public override void Emit (EmitContext ec)
1616 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1619 public override string AsString ()
1621 return Value.ToString ();
1624 public override object GetValue ()
1626 return Value;
1629 public override bool IsDefaultValue {
1630 get {
1631 return Value == 0;
1635 public override bool IsNegative {
1636 get {
1637 return Value < 0;
1641 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1643 if (target_type == TypeManager.byte_type) {
1644 if (in_checked_context){
1645 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1646 throw new OverflowException ();
1648 return new ByteConstant ((byte) Value, Location);
1650 if (target_type == TypeManager.sbyte_type) {
1651 if (in_checked_context){
1652 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1653 throw new OverflowException ();
1655 return new SByteConstant ((sbyte) Value, Location);
1657 if (target_type == TypeManager.short_type) {
1658 if (in_checked_context){
1659 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1660 throw new OverflowException ();
1662 return new ShortConstant ((short) Value, Location);
1664 if (target_type == TypeManager.ushort_type) {
1665 if (in_checked_context){
1666 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1667 throw new OverflowException ();
1669 return new UShortConstant ((ushort) Value, Location);
1671 if (target_type == TypeManager.int32_type) {
1672 if (in_checked_context){
1673 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1674 throw new OverflowException ();
1676 return new IntConstant ((int) Value, Location);
1678 if (target_type == TypeManager.uint32_type) {
1679 if (in_checked_context){
1680 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1681 throw new OverflowException ();
1683 return new UIntConstant ((uint) Value, Location);
1685 if (target_type == TypeManager.int64_type) {
1686 if (in_checked_context){
1687 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1688 throw new OverflowException ();
1690 return new LongConstant ((long) Value, Location);
1692 if (target_type == TypeManager.uint64_type) {
1693 if (in_checked_context){
1694 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1695 throw new OverflowException ();
1697 return new ULongConstant ((ulong) Value, Location);
1699 if (target_type == TypeManager.float_type)
1700 return new FloatConstant ((float) Value, Location);
1701 if (target_type == TypeManager.char_type) {
1702 if (in_checked_context){
1703 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1704 throw new OverflowException ();
1706 return new CharConstant ((char) Value, Location);
1708 if (target_type == TypeManager.decimal_type)
1709 return new DecimalConstant ((decimal) Value, Location);
1711 return null;
1716 public class DecimalConstant : Constant {
1717 public readonly decimal Value;
1719 public DecimalConstant (decimal d, Location loc):
1720 base (loc)
1722 Value = d;
1725 override public string AsString ()
1727 return Value.ToString () + "M";
1730 protected override Expression DoResolve (ResolveContext rc)
1732 type = TypeManager.decimal_type;
1733 eclass = ExprClass.Value;
1734 return this;
1737 public override object GetValue ()
1739 return (object) Value;
1742 public override void Emit (EmitContext ec)
1744 ILGenerator ig = ec.ig;
1746 int [] words = decimal.GetBits (Value);
1747 int power = (words [3] >> 16) & 0xff;
1749 if (power == 0) {
1750 if (Value <= int.MaxValue && Value >= int.MinValue) {
1751 if (TypeManager.void_decimal_ctor_int_arg == null) {
1752 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1753 TypeManager.decimal_type, loc, TypeManager.int32_type);
1755 if (TypeManager.void_decimal_ctor_int_arg == null)
1756 return;
1759 IntConstant.EmitInt (ig, (int) Value);
1760 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1761 return;
1764 if (Value <= long.MaxValue && Value >= long.MinValue) {
1765 if (TypeManager.void_decimal_ctor_long_arg == null) {
1766 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1767 TypeManager.decimal_type, loc, TypeManager.int64_type);
1769 if (TypeManager.void_decimal_ctor_long_arg == null)
1770 return;
1773 LongConstant.EmitLong (ig, (long) Value);
1774 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1775 return;
1779 IntConstant.EmitInt (ig, words [0]);
1780 IntConstant.EmitInt (ig, words [1]);
1781 IntConstant.EmitInt (ig, words [2]);
1783 // sign
1784 IntConstant.EmitInt (ig, words [3] >> 31);
1786 // power
1787 IntConstant.EmitInt (ig, power);
1789 if (TypeManager.void_decimal_ctor_five_args == null) {
1790 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1791 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1792 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1794 if (TypeManager.void_decimal_ctor_five_args == null)
1795 return;
1798 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1801 public override bool IsDefaultValue {
1802 get {
1803 return Value == 0;
1807 public override bool IsNegative {
1808 get {
1809 return Value < 0;
1813 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1815 if (target_type == TypeManager.sbyte_type)
1816 return new SByteConstant ((sbyte)Value, loc);
1817 if (target_type == TypeManager.byte_type)
1818 return new ByteConstant ((byte)Value, loc);
1819 if (target_type == TypeManager.short_type)
1820 return new ShortConstant ((short)Value, loc);
1821 if (target_type == TypeManager.ushort_type)
1822 return new UShortConstant ((ushort)Value, loc);
1823 if (target_type == TypeManager.int32_type)
1824 return new IntConstant ((int)Value, loc);
1825 if (target_type == TypeManager.uint32_type)
1826 return new UIntConstant ((uint)Value, loc);
1827 if (target_type == TypeManager.int64_type)
1828 return new LongConstant ((long)Value, loc);
1829 if (target_type == TypeManager.uint64_type)
1830 return new ULongConstant ((ulong)Value, loc);
1831 if (target_type == TypeManager.char_type)
1832 return new CharConstant ((char)Value, loc);
1833 if (target_type == TypeManager.float_type)
1834 return new FloatConstant ((float)Value, loc);
1835 if (target_type == TypeManager.double_type)
1836 return new DoubleConstant ((double)Value, loc);
1838 return null;
1843 public class StringConstant : Constant {
1844 public readonly string Value;
1846 public StringConstant (string s, Location loc):
1847 base (loc)
1849 Value = s;
1852 // FIXME: Escape the string.
1853 override public string AsString ()
1855 return "\"" + Value + "\"";
1858 protected override Expression DoResolve (ResolveContext rc)
1860 type = TypeManager.string_type;
1861 eclass = ExprClass.Value;
1862 return this;
1865 public override object GetValue ()
1867 return Value;
1870 public override void Emit (EmitContext ec)
1872 if (Value == null) {
1873 ec.ig.Emit (OpCodes.Ldnull);
1874 return;
1878 // Use string.Empty for both literals and constants even if
1879 // it's not allowed at language level
1881 if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) {
1882 if (TypeManager.string_empty == null)
1883 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
1885 if (TypeManager.string_empty != null) {
1886 ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1887 return;
1891 ec.ig.Emit (OpCodes.Ldstr, Value);
1894 public override bool IsDefaultValue {
1895 get {
1896 return Value == null;
1900 public override bool IsNegative {
1901 get {
1902 return false;
1906 public override bool IsNull {
1907 get {
1908 return IsDefaultValue;
1912 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1914 return null;
1919 // Null constant can have its own type, think of `default (Foo)'
1921 public class NullConstant : Constant
1923 public NullConstant (Type type, Location loc)
1924 : base (loc)
1926 eclass = ExprClass.Value;
1927 this.type = type;
1930 public override string AsString ()
1932 return GetSignatureForError ();
1935 protected override Expression DoResolve (ResolveContext ec)
1937 return this;
1940 public override void Emit (EmitContext ec)
1942 ec.ig.Emit (OpCodes.Ldnull);
1944 // Only to make verifier happy
1945 if (TypeManager.IsGenericParameter (type))
1946 ec.ig.Emit (OpCodes.Unbox_Any, type);
1949 public override string ExprClassName {
1950 get {
1951 return GetSignatureForError ();
1955 public override string GetSignatureForError ()
1957 return "null";
1960 public override Constant ConvertExplicitly (bool inCheckedContext, Type targetType)
1962 if (targetType.IsPointer) {
1963 if (IsLiteral || this is NullPointer)
1964 return new EmptyConstantCast (new NullPointer (loc), targetType);
1966 return null;
1969 // Exlude internal compiler types
1970 if (targetType == InternalType.AnonymousMethod)
1971 return null;
1973 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
1974 return null;
1976 if (TypeManager.IsReferenceType (targetType))
1977 return new NullConstant (targetType, loc);
1979 if (TypeManager.IsNullableType (targetType))
1980 return Nullable.LiftedNull.Create (targetType, loc);
1982 return null;
1985 public override Constant ConvertImplicitly (ResolveContext rc, Type targetType)
1987 return ConvertExplicitly (false, targetType);
1990 public override object GetValue ()
1992 return null;
1995 public override bool IsDefaultValue {
1996 get { return true; }
1999 public override bool IsNegative {
2000 get { return false; }
2003 public override bool IsNull {
2004 get { return true; }
2007 public override bool IsZeroInteger {
2008 get { return true; }
2011 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2013 type = storey.MutateType (type);
2017 /// <summary>
2018 /// The value is constant, but when emitted has a side effect. This is
2019 /// used by BitwiseAnd to ensure that the second expression is invoked
2020 /// regardless of the value of the left side.
2021 /// </summary>
2022 public class SideEffectConstant : Constant {
2023 public Constant value;
2024 Expression side_effect;
2026 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2028 this.value = value;
2029 while (side_effect is SideEffectConstant)
2030 side_effect = ((SideEffectConstant) side_effect).side_effect;
2031 this.side_effect = side_effect;
2034 public override string AsString ()
2036 return value.AsString ();
2039 protected override Expression DoResolve (ResolveContext rc)
2041 value = value.Resolve (rc);
2043 type = value.Type;
2044 eclass = ExprClass.Value;
2045 return this;
2048 public override object GetValue ()
2050 return value.GetValue ();
2053 public override void Emit (EmitContext ec)
2055 side_effect.EmitSideEffect (ec);
2056 value.Emit (ec);
2059 public override void EmitSideEffect (EmitContext ec)
2061 side_effect.EmitSideEffect (ec);
2062 value.EmitSideEffect (ec);
2065 public override bool IsDefaultValue {
2066 get { return value.IsDefaultValue; }
2069 public override bool IsNegative {
2070 get { return value.IsNegative; }
2073 public override bool IsZeroInteger {
2074 get { return value.IsZeroInteger; }
2077 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
2079 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2080 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);