2010-05-19 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / constant.cs
blobc04ad0246df1417ee4d111d3245a9f5e4e2370c1
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 /// <summary>
43 /// This is used to obtain the actual value of the literal
44 /// cast into an object.
45 /// </summary>
46 public abstract object GetValue ();
48 public virtual object GetTypedValue ()
50 return GetValue ();
53 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
55 if (!expl && IsLiteral &&
56 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
57 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
58 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
59 AsString (), TypeManager.CSharpName (target));
60 } else {
61 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
65 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
67 Constant c = ConvertImplicitly (ec, type);
68 if (c == null)
69 Error_ValueCannotBeConverted (ec, loc, type, false);
71 return c;
74 public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
76 if (this.type == type)
77 return this;
79 if (Convert.ImplicitNumericConversion (this, type) == null)
80 return null;
82 bool fail;
83 object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
84 if (fail){
86 // We should always catch the error before this is ever
87 // reached, by calling Convert.ImplicitStandardConversionExists
89 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
90 TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
93 return CreateConstant (rc, type, constant_value, loc);
97 // Returns a constant instance based on Type
99 public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc)
101 return CreateConstantFromValue (t, v, loc).Resolve (rc);
104 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
106 if (t == TypeManager.int32_type)
107 return new IntConstant ((int) v, loc);
108 if (t == TypeManager.string_type)
109 return new StringConstant ((string) v, loc);
110 if (t == TypeManager.uint32_type)
111 return new UIntConstant ((uint) v, loc);
112 if (t == TypeManager.int64_type)
113 return new LongConstant ((long) v, loc);
114 if (t == TypeManager.uint64_type)
115 return new ULongConstant ((ulong) v, loc);
116 if (t == TypeManager.float_type)
117 return new FloatConstant ((float) v, loc);
118 if (t == TypeManager.double_type)
119 return new DoubleConstant ((double) v, loc);
120 if (t == TypeManager.short_type)
121 return new ShortConstant ((short)v, loc);
122 if (t == TypeManager.ushort_type)
123 return new UShortConstant ((ushort)v, loc);
124 if (t == TypeManager.sbyte_type)
125 return new SByteConstant ((sbyte)v, loc);
126 if (t == TypeManager.byte_type)
127 return new ByteConstant ((byte)v, loc);
128 if (t == TypeManager.char_type)
129 return new CharConstant ((char)v, loc);
130 if (t == TypeManager.bool_type)
131 return new BoolConstant ((bool) v, loc);
132 if (t == TypeManager.decimal_type)
133 return new DecimalConstant ((decimal) v, loc);
134 if (TypeManager.IsEnumType (t)) {
135 var real_type = EnumSpec.GetUnderlyingType (t);
136 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
138 if (v == null) {
139 if (TypeManager.IsNullableType (t))
140 return Nullable.LiftedNull.Create (t, loc);
142 if (TypeManager.IsReferenceType (t))
143 return new NullConstant (t, loc);
146 throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
147 v, TypeManager.CSharpName (t));
150 public override Expression CreateExpressionTree (ResolveContext ec)
152 Arguments args = new Arguments (2);
153 args.Add (new Argument (this));
154 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
156 return CreateExpressionFactoryCall (ec, "Constant", args);
160 /// <summary>
161 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
162 /// It throws OverflowException
163 /// </summary>
164 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
165 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
167 /// <summary>
168 /// Attempts to do a compile-time folding of a constant cast.
169 /// </summary>
170 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
172 try {
173 return TryReduce (ec, target_type);
175 catch (OverflowException) {
176 if (ec.ConstantCheckState) {
177 ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
178 GetValue ().ToString (), TypeManager.CSharpName (target_type));
179 } else {
180 Error_ValueCannotBeConverted (ec, loc, target_type, false);
183 return New.Constantify (target_type).Resolve (ec);
187 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
189 if (Type == target_type)
190 return this;
192 Constant c;
193 if (TypeManager.IsEnumType (target_type)) {
194 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
195 if (c == null)
196 return null;
198 return new EnumConstant (c, target_type).Resolve (ec);
201 c = ConvertExplicitly (ec.ConstantCheckState, target_type);
202 if (c != null)
203 c = c.Resolve (ec);
205 return c;
208 /// <summary>
209 /// Need to pass type as the constant can require a boxing
210 /// and in such case no optimization is possible
211 /// </summary>
212 public bool IsDefaultInitializer (TypeSpec type)
214 if (type == Type)
215 return IsDefaultValue;
217 return this is NullLiteral;
220 public abstract bool IsDefaultValue {
221 get;
224 public abstract bool IsNegative {
225 get;
229 // When constant is declared as literal
231 public virtual bool IsLiteral {
232 get { return false; }
235 public virtual bool IsOneInteger {
236 get { return false; }
240 // Returns true iff 1) the stack type of this is one of Object,
241 // int32, int64 and 2) this == 0 or this == null.
243 public virtual bool IsZeroInteger {
244 get { return false; }
247 public override void EmitSideEffect (EmitContext ec)
249 // do nothing
252 protected override void CloneTo (CloneContext clonectx, Expression target)
254 // CloneTo: Nothing, we do not keep any state on this expression
257 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
259 return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
262 public new Constant Resolve (ResolveContext rc)
264 if (eclass != ExprClass.Unresolved)
265 return this;
267 // Resolved constant has to be still a constant
268 Constant c = (Constant) DoResolve (rc);
269 if (c == null)
270 return null;
272 if ((c.eclass & ExprClass.Value) == 0) {
273 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
274 return null;
277 if (c.type == null)
278 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
280 return c;
284 public abstract class IntegralConstant : Constant {
285 protected IntegralConstant (Location loc) :
286 base (loc)
290 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
292 try {
293 ConvertExplicitly (true, target);
294 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
296 catch
298 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
299 GetValue ().ToString (), TypeManager.CSharpName (target));
303 public abstract Constant Increment ();
306 public class BoolConstant : Constant {
307 public readonly bool Value;
309 public BoolConstant (bool val, Location loc):
310 base (loc)
312 Value = val;
315 override public string AsString ()
317 return Value ? "true" : "false";
320 protected override Expression DoResolve (ResolveContext ec)
322 type = TypeManager.bool_type;
323 eclass = ExprClass.Value;
324 return this;
327 public override object GetValue ()
329 return (object) Value;
332 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
334 enc.Stream.Write (Value);
337 public override void Emit (EmitContext ec)
339 if (Value)
340 ec.Emit (OpCodes.Ldc_I4_1);
341 else
342 ec.Emit (OpCodes.Ldc_I4_0);
345 public override bool IsDefaultValue {
346 get {
347 return !Value;
351 public override bool IsNegative {
352 get {
353 return false;
357 public override bool IsZeroInteger {
358 get { return Value == false; }
361 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
363 return null;
368 public class ByteConstant : IntegralConstant {
369 public readonly byte Value;
371 public ByteConstant (byte v, Location loc):
372 base (loc)
374 Value = v;
377 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
379 enc.Stream.Write (Value);
382 public override void Emit (EmitContext ec)
384 ec.EmitInt (Value);
387 public override string AsString ()
389 return Value.ToString ();
392 protected override Expression DoResolve (ResolveContext ec)
394 type = TypeManager.byte_type;
395 eclass = ExprClass.Value;
396 return this;
399 public override object GetValue ()
401 return Value;
404 public override Constant Increment ()
406 return new ByteConstant (checked ((byte)(Value + 1)), loc);
409 public override bool IsDefaultValue {
410 get {
411 return Value == 0;
415 public override bool IsOneInteger {
416 get {
417 return Value == 1;
421 public override bool IsNegative {
422 get {
423 return false;
427 public override bool IsZeroInteger {
428 get { return Value == 0; }
431 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
433 if (target_type == TypeManager.sbyte_type) {
434 if (in_checked_context){
435 if (Value > SByte.MaxValue)
436 throw new OverflowException ();
438 return new SByteConstant ((sbyte) Value, Location);
440 if (target_type == TypeManager.short_type)
441 return new ShortConstant ((short) Value, Location);
442 if (target_type == TypeManager.ushort_type)
443 return new UShortConstant ((ushort) Value, Location);
444 if (target_type == TypeManager.int32_type)
445 return new IntConstant ((int) Value, Location);
446 if (target_type == TypeManager.uint32_type)
447 return new UIntConstant ((uint) Value, Location);
448 if (target_type == TypeManager.int64_type)
449 return new LongConstant ((long) Value, Location);
450 if (target_type == TypeManager.uint64_type)
451 return new ULongConstant ((ulong) Value, Location);
452 if (target_type == TypeManager.float_type)
453 return new FloatConstant ((float) Value, Location);
454 if (target_type == TypeManager.double_type)
455 return new DoubleConstant ((double) Value, Location);
456 if (target_type == TypeManager.char_type)
457 return new CharConstant ((char) Value, Location);
458 if (target_type == TypeManager.decimal_type)
459 return new DecimalConstant ((decimal) Value, Location);
461 return null;
466 public class CharConstant : Constant {
467 public readonly char Value;
469 public CharConstant (char v, Location loc):
470 base (loc)
472 Value = v;
475 protected override Expression DoResolve (ResolveContext rc)
477 type = TypeManager.char_type;
478 eclass = ExprClass.Value;
479 return this;
482 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
484 enc.Stream.Write ((ushort) Value);
487 public override void Emit (EmitContext ec)
489 ec.EmitInt (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, TypeSpec 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 EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
608 enc.Stream.Write (Value);
611 public override void Emit (EmitContext ec)
613 ec.EmitInt (Value);
616 public override string AsString ()
618 return Value.ToString ();
621 public override object GetValue ()
623 return Value;
626 public override Constant Increment ()
628 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
631 public override bool IsDefaultValue {
632 get {
633 return Value == 0;
637 public override bool IsNegative {
638 get {
639 return Value < 0;
643 public override bool IsOneInteger {
644 get {
645 return Value == 1;
649 public override bool IsZeroInteger {
650 get { return Value == 0; }
653 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
655 if (target_type == TypeManager.byte_type) {
656 if (in_checked_context && Value < 0)
657 throw new OverflowException ();
658 return new ByteConstant ((byte) Value, Location);
660 if (target_type == TypeManager.short_type)
661 return new ShortConstant ((short) Value, Location);
662 if (target_type == TypeManager.ushort_type) {
663 if (in_checked_context && Value < 0)
664 throw new OverflowException ();
665 return new UShortConstant ((ushort) Value, Location);
666 } if (target_type == TypeManager.int32_type)
667 return new IntConstant ((int) Value, Location);
668 if (target_type == TypeManager.uint32_type) {
669 if (in_checked_context && Value < 0)
670 throw new OverflowException ();
671 return new UIntConstant ((uint) Value, Location);
672 } if (target_type == TypeManager.int64_type)
673 return new LongConstant ((long) Value, Location);
674 if (target_type == TypeManager.uint64_type) {
675 if (in_checked_context && Value < 0)
676 throw new OverflowException ();
677 return new ULongConstant ((ulong) Value, Location);
679 if (target_type == TypeManager.float_type)
680 return new FloatConstant ((float) Value, Location);
681 if (target_type == TypeManager.double_type)
682 return new DoubleConstant ((double) Value, Location);
683 if (target_type == TypeManager.char_type) {
684 if (in_checked_context && Value < 0)
685 throw new OverflowException ();
686 return new CharConstant ((char) Value, Location);
688 if (target_type == TypeManager.decimal_type)
689 return new DecimalConstant ((decimal) Value, Location);
691 return null;
696 public class ShortConstant : IntegralConstant {
697 public readonly short Value;
699 public ShortConstant (short v, Location loc):
700 base (loc)
702 Value = v;
705 protected override Expression DoResolve (ResolveContext rc)
707 type = TypeManager.short_type;
708 eclass = ExprClass.Value;
709 return this;
712 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
714 enc.Stream.Write (Value);
717 public override void Emit (EmitContext ec)
719 ec.EmitInt (Value);
722 public override string AsString ()
724 return Value.ToString ();
727 public override object GetValue ()
729 return Value;
732 public override Constant Increment ()
734 return new ShortConstant (checked((short)(Value + 1)), loc);
737 public override bool IsDefaultValue {
738 get {
739 return Value == 0;
743 public override bool IsZeroInteger {
744 get { return Value == 0; }
747 public override bool IsNegative {
748 get {
749 return Value < 0;
753 public override bool IsOneInteger {
754 get {
755 return Value == 1;
759 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
761 if (target_type == TypeManager.byte_type) {
762 if (in_checked_context){
763 if (Value < Byte.MinValue || Value > Byte.MaxValue)
764 throw new OverflowException ();
766 return new ByteConstant ((byte) Value, Location);
768 if (target_type == TypeManager.sbyte_type) {
769 if (in_checked_context){
770 if (Value < SByte.MinValue || Value > SByte.MaxValue)
771 throw new OverflowException ();
773 return new SByteConstant ((sbyte) Value, Location);
775 if (target_type == TypeManager.ushort_type) {
776 if (in_checked_context && Value < 0)
777 throw new OverflowException ();
779 return new UShortConstant ((ushort) Value, Location);
781 if (target_type == TypeManager.int32_type)
782 return new IntConstant ((int) Value, Location);
783 if (target_type == TypeManager.uint32_type) {
784 if (in_checked_context && Value < 0)
785 throw new OverflowException ();
786 return new UIntConstant ((uint) Value, Location);
788 if (target_type == TypeManager.int64_type)
789 return new LongConstant ((long) Value, Location);
790 if (target_type == TypeManager.uint64_type) {
791 if (in_checked_context && Value < 0)
792 throw new OverflowException ();
793 return new ULongConstant ((ulong) Value, Location);
795 if (target_type == TypeManager.float_type)
796 return new FloatConstant ((float) Value, Location);
797 if (target_type == TypeManager.double_type)
798 return new DoubleConstant ((double) Value, Location);
799 if (target_type == TypeManager.char_type) {
800 if (in_checked_context){
801 if (Value < Char.MinValue)
802 throw new OverflowException ();
804 return new CharConstant ((char) Value, Location);
806 if (target_type == TypeManager.decimal_type)
807 return new DecimalConstant ((decimal) Value, Location);
809 return null;
814 public class UShortConstant : IntegralConstant {
815 public readonly ushort Value;
817 public UShortConstant (ushort v, Location loc):
818 base (loc)
820 Value = v;
823 protected override Expression DoResolve (ResolveContext rc)
825 type = TypeManager.ushort_type;
826 eclass = ExprClass.Value;
827 return this;
830 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
832 enc.Stream.Write (Value);
835 public override void Emit (EmitContext ec)
837 ec.EmitInt (Value);
840 public override string AsString ()
842 return Value.ToString ();
845 public override object GetValue ()
847 return Value;
850 public override Constant Increment ()
852 return new UShortConstant (checked((ushort)(Value + 1)), loc);
855 public override bool IsDefaultValue {
856 get {
857 return Value == 0;
861 public override bool IsNegative {
862 get {
863 return false;
867 public override bool IsOneInteger {
868 get {
869 return Value == 1;
873 public override bool IsZeroInteger {
874 get { return Value == 0; }
877 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
879 if (target_type == TypeManager.byte_type) {
880 if (in_checked_context){
881 if (Value > Byte.MaxValue)
882 throw new OverflowException ();
884 return new ByteConstant ((byte) Value, Location);
886 if (target_type == TypeManager.sbyte_type) {
887 if (in_checked_context){
888 if (Value > SByte.MaxValue)
889 throw new OverflowException ();
891 return new SByteConstant ((sbyte) Value, Location);
893 if (target_type == TypeManager.short_type) {
894 if (in_checked_context){
895 if (Value > Int16.MaxValue)
896 throw new OverflowException ();
898 return new ShortConstant ((short) Value, Location);
900 if (target_type == TypeManager.int32_type)
901 return new IntConstant ((int) Value, Location);
902 if (target_type == TypeManager.uint32_type)
903 return new UIntConstant ((uint) Value, Location);
904 if (target_type == TypeManager.int64_type)
905 return new LongConstant ((long) Value, Location);
906 if (target_type == TypeManager.uint64_type)
907 return new ULongConstant ((ulong) Value, Location);
908 if (target_type == TypeManager.float_type)
909 return new FloatConstant ((float) Value, Location);
910 if (target_type == TypeManager.double_type)
911 return new DoubleConstant ((double) Value, Location);
912 if (target_type == TypeManager.char_type) {
913 if (in_checked_context){
914 if (Value > Char.MaxValue)
915 throw new OverflowException ();
917 return new CharConstant ((char) Value, Location);
919 if (target_type == TypeManager.decimal_type)
920 return new DecimalConstant ((decimal) Value, Location);
922 return null;
926 public class IntConstant : IntegralConstant {
927 public readonly int Value;
929 public IntConstant (int v, Location loc):
930 base (loc)
932 Value = v;
935 protected override Expression DoResolve (ResolveContext rc)
937 type = TypeManager.int32_type;
938 eclass = ExprClass.Value;
939 return this;
942 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
944 enc.Stream.Write (Value);
947 public override void Emit (EmitContext ec)
949 ec.EmitInt (Value);
952 public override string AsString ()
954 return Value.ToString ();
957 public override object GetValue ()
959 return Value;
962 public override Constant Increment ()
964 return new IntConstant (checked(Value + 1), loc);
967 public override bool IsDefaultValue {
968 get {
969 return Value == 0;
973 public override bool IsNegative {
974 get {
975 return Value < 0;
979 public override bool IsOneInteger {
980 get {
981 return Value == 1;
985 public override bool IsZeroInteger {
986 get { return Value == 0; }
989 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
991 if (target_type == TypeManager.byte_type) {
992 if (in_checked_context){
993 if (Value < Byte.MinValue || Value > Byte.MaxValue)
994 throw new OverflowException ();
996 return new ByteConstant ((byte) Value, Location);
998 if (target_type == TypeManager.sbyte_type) {
999 if (in_checked_context){
1000 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1001 throw new OverflowException ();
1003 return new SByteConstant ((sbyte) Value, Location);
1005 if (target_type == TypeManager.short_type) {
1006 if (in_checked_context){
1007 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1008 throw new OverflowException ();
1010 return new ShortConstant ((short) Value, Location);
1012 if (target_type == TypeManager.ushort_type) {
1013 if (in_checked_context){
1014 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1015 throw new OverflowException ();
1017 return new UShortConstant ((ushort) Value, Location);
1019 if (target_type == TypeManager.uint32_type) {
1020 if (in_checked_context){
1021 if (Value < UInt32.MinValue)
1022 throw new OverflowException ();
1024 return new UIntConstant ((uint) Value, Location);
1026 if (target_type == TypeManager.int64_type)
1027 return new LongConstant ((long) Value, Location);
1028 if (target_type == TypeManager.uint64_type) {
1029 if (in_checked_context && Value < 0)
1030 throw new OverflowException ();
1031 return new ULongConstant ((ulong) Value, Location);
1033 if (target_type == TypeManager.float_type)
1034 return new FloatConstant ((float) Value, Location);
1035 if (target_type == TypeManager.double_type)
1036 return new DoubleConstant ((double) Value, Location);
1037 if (target_type == TypeManager.char_type) {
1038 if (in_checked_context){
1039 if (Value < Char.MinValue || Value > Char.MaxValue)
1040 throw new OverflowException ();
1042 return new CharConstant ((char) Value, Location);
1044 if (target_type == TypeManager.decimal_type)
1045 return new DecimalConstant ((decimal) Value, Location);
1047 return null;
1050 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1052 if (this.type == type)
1053 return this;
1055 Constant c = TryImplicitIntConversion (type);
1056 if (c != null)
1057 return c.Resolve (rc);
1059 return base.ConvertImplicitly (rc, type);
1062 /// <summary>
1063 /// Attempts to perform an implicit constant conversion of the IntConstant
1064 /// into a different data type using casts (See Implicit Constant
1065 /// Expression Conversions)
1066 /// </summary>
1067 Constant TryImplicitIntConversion (TypeSpec target_type)
1069 if (target_type == TypeManager.sbyte_type) {
1070 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1071 return new SByteConstant ((sbyte) Value, loc);
1073 else if (target_type == TypeManager.byte_type) {
1074 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1075 return new ByteConstant ((byte) Value, loc);
1077 else if (target_type == TypeManager.short_type) {
1078 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1079 return new ShortConstant ((short) Value, loc);
1081 else if (target_type == TypeManager.ushort_type) {
1082 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1083 return new UShortConstant ((ushort) Value, loc);
1085 else if (target_type == TypeManager.uint32_type) {
1086 if (Value >= 0)
1087 return new UIntConstant ((uint) Value, loc);
1089 else if (target_type == TypeManager.uint64_type) {
1091 // we can optimize this case: a positive int32
1092 // always fits on a uint64. But we need an opcode
1093 // to do it.
1095 if (Value >= 0)
1096 return new ULongConstant ((ulong) Value, loc);
1098 else if (target_type == TypeManager.double_type)
1099 return new DoubleConstant ((double) Value, loc);
1100 else if (target_type == TypeManager.float_type)
1101 return new FloatConstant ((float) Value, loc);
1103 return null;
1107 public class UIntConstant : IntegralConstant {
1108 public readonly uint Value;
1110 public UIntConstant (uint v, Location loc):
1111 base (loc)
1113 Value = v;
1116 protected override Expression DoResolve (ResolveContext rc)
1118 type = TypeManager.uint32_type;
1119 eclass = ExprClass.Value;
1120 return this;
1123 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1125 enc.Stream.Write (Value);
1128 public override void Emit (EmitContext ec)
1130 ec.EmitInt (unchecked ((int) Value));
1133 public override string AsString ()
1135 return Value.ToString ();
1138 public override object GetValue ()
1140 return Value;
1143 public override Constant Increment ()
1145 return new UIntConstant (checked(Value + 1), loc);
1148 public override bool IsDefaultValue {
1149 get {
1150 return Value == 0;
1154 public override bool IsNegative {
1155 get {
1156 return false;
1160 public override bool IsOneInteger {
1161 get {
1162 return Value == 1;
1166 public override bool IsZeroInteger {
1167 get { return Value == 0; }
1170 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1172 if (target_type == TypeManager.byte_type) {
1173 if (in_checked_context){
1174 if (Value < Char.MinValue || Value > Char.MaxValue)
1175 throw new OverflowException ();
1177 return new ByteConstant ((byte) Value, Location);
1179 if (target_type == TypeManager.sbyte_type) {
1180 if (in_checked_context){
1181 if (Value > SByte.MaxValue)
1182 throw new OverflowException ();
1184 return new SByteConstant ((sbyte) Value, Location);
1186 if (target_type == TypeManager.short_type) {
1187 if (in_checked_context){
1188 if (Value > Int16.MaxValue)
1189 throw new OverflowException ();
1191 return new ShortConstant ((short) Value, Location);
1193 if (target_type == TypeManager.ushort_type) {
1194 if (in_checked_context){
1195 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1196 throw new OverflowException ();
1198 return new UShortConstant ((ushort) Value, Location);
1200 if (target_type == TypeManager.int32_type) {
1201 if (in_checked_context){
1202 if (Value > Int32.MaxValue)
1203 throw new OverflowException ();
1205 return new IntConstant ((int) Value, Location);
1207 if (target_type == TypeManager.int64_type)
1208 return new LongConstant ((long) Value, Location);
1209 if (target_type == TypeManager.uint64_type)
1210 return new ULongConstant ((ulong) Value, Location);
1211 if (target_type == TypeManager.float_type)
1212 return new FloatConstant ((float) Value, Location);
1213 if (target_type == TypeManager.double_type)
1214 return new DoubleConstant ((double) Value, Location);
1215 if (target_type == TypeManager.char_type) {
1216 if (in_checked_context){
1217 if (Value < Char.MinValue || Value > Char.MaxValue)
1218 throw new OverflowException ();
1220 return new CharConstant ((char) Value, Location);
1222 if (target_type == TypeManager.decimal_type)
1223 return new DecimalConstant ((decimal) Value, Location);
1225 return null;
1230 public class LongConstant : IntegralConstant {
1231 public readonly long Value;
1233 public LongConstant (long v, Location loc):
1234 base (loc)
1236 Value = v;
1239 protected override Expression DoResolve (ResolveContext rc)
1241 type = TypeManager.int64_type;
1242 eclass = ExprClass.Value;
1243 return this;
1246 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1248 enc.Stream.Write (Value);
1251 public override void Emit (EmitContext ec)
1253 ec.EmitLong (Value);
1256 public override string AsString ()
1258 return Value.ToString ();
1261 public override object GetValue ()
1263 return Value;
1266 public override Constant Increment ()
1268 return new LongConstant (checked(Value + 1), loc);
1271 public override bool IsDefaultValue {
1272 get {
1273 return Value == 0;
1277 public override bool IsNegative {
1278 get {
1279 return Value < 0;
1283 public override bool IsOneInteger {
1284 get {
1285 return Value == 1;
1289 public override bool IsZeroInteger {
1290 get { return Value == 0; }
1293 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1295 if (target_type == TypeManager.byte_type) {
1296 if (in_checked_context){
1297 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1298 throw new OverflowException ();
1300 return new ByteConstant ((byte) Value, Location);
1302 if (target_type == TypeManager.sbyte_type) {
1303 if (in_checked_context){
1304 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1305 throw new OverflowException ();
1307 return new SByteConstant ((sbyte) Value, Location);
1309 if (target_type == TypeManager.short_type) {
1310 if (in_checked_context){
1311 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1312 throw new OverflowException ();
1314 return new ShortConstant ((short) Value, Location);
1316 if (target_type == TypeManager.ushort_type) {
1317 if (in_checked_context){
1318 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1319 throw new OverflowException ();
1321 return new UShortConstant ((ushort) Value, Location);
1323 if (target_type == TypeManager.int32_type) {
1324 if (in_checked_context){
1325 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1326 throw new OverflowException ();
1328 return new IntConstant ((int) Value, Location);
1330 if (target_type == TypeManager.uint32_type) {
1331 if (in_checked_context){
1332 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1333 throw new OverflowException ();
1335 return new UIntConstant ((uint) Value, Location);
1337 if (target_type == TypeManager.uint64_type) {
1338 if (in_checked_context && Value < 0)
1339 throw new OverflowException ();
1340 return new ULongConstant ((ulong) Value, Location);
1342 if (target_type == TypeManager.float_type)
1343 return new FloatConstant ((float) Value, Location);
1344 if (target_type == TypeManager.double_type)
1345 return new DoubleConstant ((double) Value, Location);
1346 if (target_type == TypeManager.char_type) {
1347 if (in_checked_context){
1348 if (Value < Char.MinValue || Value > Char.MaxValue)
1349 throw new OverflowException ();
1351 return new CharConstant ((char) Value, Location);
1353 if (target_type == TypeManager.decimal_type)
1354 return new DecimalConstant ((decimal) Value, Location);
1356 return null;
1359 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1361 if (Value >= 0 && type == TypeManager.uint64_type) {
1362 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1365 return base.ConvertImplicitly (rc, type);
1369 public class ULongConstant : IntegralConstant {
1370 public readonly ulong Value;
1372 public ULongConstant (ulong v, Location loc):
1373 base (loc)
1375 Value = v;
1378 protected override Expression DoResolve (ResolveContext rc)
1380 type = TypeManager.uint64_type;
1381 eclass = ExprClass.Value;
1382 return this;
1385 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1387 enc.Stream.Write (Value);
1390 public override void Emit (EmitContext ec)
1392 ec.EmitLong (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 IsOneInteger {
1423 get {
1424 return Value == 1;
1428 public override bool IsZeroInteger {
1429 get { return Value == 0; }
1432 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1434 if (target_type == TypeManager.byte_type) {
1435 if (in_checked_context && Value > Byte.MaxValue)
1436 throw new OverflowException ();
1437 return new ByteConstant ((byte) Value, Location);
1439 if (target_type == TypeManager.sbyte_type) {
1440 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1441 throw new OverflowException ();
1442 return new SByteConstant ((sbyte) Value, Location);
1444 if (target_type == TypeManager.short_type) {
1445 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1446 throw new OverflowException ();
1447 return new ShortConstant ((short) Value, Location);
1449 if (target_type == TypeManager.ushort_type) {
1450 if (in_checked_context && Value > UInt16.MaxValue)
1451 throw new OverflowException ();
1452 return new UShortConstant ((ushort) Value, Location);
1454 if (target_type == TypeManager.int32_type) {
1455 if (in_checked_context && Value > UInt32.MaxValue)
1456 throw new OverflowException ();
1457 return new IntConstant ((int) Value, Location);
1459 if (target_type == TypeManager.uint32_type) {
1460 if (in_checked_context && Value > UInt32.MaxValue)
1461 throw new OverflowException ();
1462 return new UIntConstant ((uint) Value, Location);
1464 if (target_type == TypeManager.int64_type) {
1465 if (in_checked_context && Value > Int64.MaxValue)
1466 throw new OverflowException ();
1467 return new LongConstant ((long) Value, Location);
1469 if (target_type == TypeManager.float_type)
1470 return new FloatConstant ((float) Value, Location);
1471 if (target_type == TypeManager.double_type)
1472 return new DoubleConstant ((double) Value, Location);
1473 if (target_type == TypeManager.char_type) {
1474 if (in_checked_context && Value > Char.MaxValue)
1475 throw new OverflowException ();
1476 return new CharConstant ((char) Value, Location);
1478 if (target_type == TypeManager.decimal_type)
1479 return new DecimalConstant ((decimal) Value, Location);
1481 return null;
1486 public class FloatConstant : Constant {
1487 public float Value;
1489 public FloatConstant (float v, Location loc):
1490 base (loc)
1492 Value = v;
1495 protected override Expression DoResolve (ResolveContext rc)
1497 type = TypeManager.float_type;
1498 eclass = ExprClass.Value;
1499 return this;
1502 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1504 enc.Stream.Write (Value);
1507 public override void Emit (EmitContext ec)
1509 ec.Emit (OpCodes.Ldc_R4, Value);
1512 public override string AsString ()
1514 return Value.ToString ();
1517 public override object GetValue ()
1519 return Value;
1522 public override bool IsDefaultValue {
1523 get {
1524 return Value == 0;
1528 public override bool IsNegative {
1529 get {
1530 return Value < 0;
1534 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1536 if (target_type == TypeManager.byte_type) {
1537 if (in_checked_context){
1538 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1539 throw new OverflowException ();
1541 return new ByteConstant ((byte) Value, Location);
1543 if (target_type == TypeManager.sbyte_type) {
1544 if (in_checked_context){
1545 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1546 throw new OverflowException ();
1548 return new SByteConstant ((sbyte) Value, Location);
1550 if (target_type == TypeManager.short_type) {
1551 if (in_checked_context){
1552 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1553 throw new OverflowException ();
1555 return new ShortConstant ((short) Value, Location);
1557 if (target_type == TypeManager.ushort_type) {
1558 if (in_checked_context){
1559 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1560 throw new OverflowException ();
1562 return new UShortConstant ((ushort) Value, Location);
1564 if (target_type == TypeManager.int32_type) {
1565 if (in_checked_context){
1566 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1567 throw new OverflowException ();
1569 return new IntConstant ((int) Value, Location);
1571 if (target_type == TypeManager.uint32_type) {
1572 if (in_checked_context){
1573 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1574 throw new OverflowException ();
1576 return new UIntConstant ((uint) Value, Location);
1578 if (target_type == TypeManager.int64_type) {
1579 if (in_checked_context){
1580 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1581 throw new OverflowException ();
1583 return new LongConstant ((long) Value, Location);
1585 if (target_type == TypeManager.uint64_type) {
1586 if (in_checked_context){
1587 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1588 throw new OverflowException ();
1590 return new ULongConstant ((ulong) Value, Location);
1592 if (target_type == TypeManager.double_type)
1593 return new DoubleConstant ((double) Value, Location);
1594 if (target_type == TypeManager.char_type) {
1595 if (in_checked_context){
1596 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1597 throw new OverflowException ();
1599 return new CharConstant ((char) Value, Location);
1601 if (target_type == TypeManager.decimal_type)
1602 return new DecimalConstant ((decimal) Value, Location);
1604 return null;
1609 public class DoubleConstant : Constant {
1610 public double Value;
1612 public DoubleConstant (double v, Location loc):
1613 base (loc)
1615 Value = v;
1618 protected override Expression DoResolve (ResolveContext rc)
1620 type = TypeManager.double_type;
1621 eclass = ExprClass.Value;
1622 return this;
1625 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1627 enc.Stream.Write (Value);
1630 public override void Emit (EmitContext ec)
1632 ec.Emit (OpCodes.Ldc_R8, Value);
1635 public override string AsString ()
1637 return Value.ToString ();
1640 public override object GetValue ()
1642 return Value;
1645 public override bool IsDefaultValue {
1646 get {
1647 return Value == 0;
1651 public override bool IsNegative {
1652 get {
1653 return Value < 0;
1657 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1659 if (target_type == TypeManager.byte_type) {
1660 if (in_checked_context){
1661 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1662 throw new OverflowException ();
1664 return new ByteConstant ((byte) Value, Location);
1666 if (target_type == TypeManager.sbyte_type) {
1667 if (in_checked_context){
1668 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1669 throw new OverflowException ();
1671 return new SByteConstant ((sbyte) Value, Location);
1673 if (target_type == TypeManager.short_type) {
1674 if (in_checked_context){
1675 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1676 throw new OverflowException ();
1678 return new ShortConstant ((short) Value, Location);
1680 if (target_type == TypeManager.ushort_type) {
1681 if (in_checked_context){
1682 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1683 throw new OverflowException ();
1685 return new UShortConstant ((ushort) Value, Location);
1687 if (target_type == TypeManager.int32_type) {
1688 if (in_checked_context){
1689 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1690 throw new OverflowException ();
1692 return new IntConstant ((int) Value, Location);
1694 if (target_type == TypeManager.uint32_type) {
1695 if (in_checked_context){
1696 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1697 throw new OverflowException ();
1699 return new UIntConstant ((uint) Value, Location);
1701 if (target_type == TypeManager.int64_type) {
1702 if (in_checked_context){
1703 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1704 throw new OverflowException ();
1706 return new LongConstant ((long) Value, Location);
1708 if (target_type == TypeManager.uint64_type) {
1709 if (in_checked_context){
1710 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1711 throw new OverflowException ();
1713 return new ULongConstant ((ulong) Value, Location);
1715 if (target_type == TypeManager.float_type)
1716 return new FloatConstant ((float) Value, Location);
1717 if (target_type == TypeManager.char_type) {
1718 if (in_checked_context){
1719 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1720 throw new OverflowException ();
1722 return new CharConstant ((char) Value, Location);
1724 if (target_type == TypeManager.decimal_type)
1725 return new DecimalConstant ((decimal) Value, Location);
1727 return null;
1732 public class DecimalConstant : Constant {
1733 public readonly decimal Value;
1735 public DecimalConstant (decimal d, Location loc):
1736 base (loc)
1738 Value = d;
1741 override public string AsString ()
1743 return Value.ToString () + "M";
1746 protected override Expression DoResolve (ResolveContext rc)
1748 type = TypeManager.decimal_type;
1749 eclass = ExprClass.Value;
1750 return this;
1753 public override object GetValue ()
1755 return (object) Value;
1758 public override void Emit (EmitContext ec)
1760 int [] words = decimal.GetBits (Value);
1761 int power = (words [3] >> 16) & 0xff;
1763 if (power == 0) {
1764 if (Value <= int.MaxValue && Value >= int.MinValue) {
1765 if (TypeManager.void_decimal_ctor_int_arg == null) {
1766 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1767 TypeManager.decimal_type, loc, TypeManager.int32_type);
1769 if (TypeManager.void_decimal_ctor_int_arg == null)
1770 return;
1773 ec.EmitInt ((int) Value);
1774 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1775 return;
1778 if (Value <= long.MaxValue && Value >= long.MinValue) {
1779 if (TypeManager.void_decimal_ctor_long_arg == null) {
1780 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1781 TypeManager.decimal_type, loc, TypeManager.int64_type);
1783 if (TypeManager.void_decimal_ctor_long_arg == null)
1784 return;
1787 ec.EmitLong ((long) Value);
1788 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1789 return;
1793 ec.EmitInt (words [0]);
1794 ec.EmitInt (words [1]);
1795 ec.EmitInt (words [2]);
1797 // sign
1798 ec.EmitInt (words [3] >> 31);
1800 // power
1801 ec.EmitInt (power);
1803 if (TypeManager.void_decimal_ctor_five_args == null) {
1804 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1805 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1806 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1808 if (TypeManager.void_decimal_ctor_five_args == null)
1809 return;
1812 ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1815 public override bool IsDefaultValue {
1816 get {
1817 return Value == 0;
1821 public override bool IsNegative {
1822 get {
1823 return Value < 0;
1827 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1829 if (target_type == TypeManager.sbyte_type)
1830 return new SByteConstant ((sbyte)Value, loc);
1831 if (target_type == TypeManager.byte_type)
1832 return new ByteConstant ((byte)Value, loc);
1833 if (target_type == TypeManager.short_type)
1834 return new ShortConstant ((short)Value, loc);
1835 if (target_type == TypeManager.ushort_type)
1836 return new UShortConstant ((ushort)Value, loc);
1837 if (target_type == TypeManager.int32_type)
1838 return new IntConstant ((int)Value, loc);
1839 if (target_type == TypeManager.uint32_type)
1840 return new UIntConstant ((uint)Value, loc);
1841 if (target_type == TypeManager.int64_type)
1842 return new LongConstant ((long)Value, loc);
1843 if (target_type == TypeManager.uint64_type)
1844 return new ULongConstant ((ulong)Value, loc);
1845 if (target_type == TypeManager.char_type)
1846 return new CharConstant ((char)Value, loc);
1847 if (target_type == TypeManager.float_type)
1848 return new FloatConstant ((float)Value, loc);
1849 if (target_type == TypeManager.double_type)
1850 return new DoubleConstant ((double)Value, loc);
1852 return null;
1857 public class StringConstant : Constant {
1858 public readonly string Value;
1860 public StringConstant (string s, Location loc):
1861 base (loc)
1863 Value = s;
1866 // FIXME: Escape the string.
1867 override public string AsString ()
1869 return "\"" + Value + "\"";
1872 protected override Expression DoResolve (ResolveContext rc)
1874 type = TypeManager.string_type;
1875 eclass = ExprClass.Value;
1876 return this;
1879 public override object GetValue ()
1881 return Value;
1884 public override void Emit (EmitContext ec)
1886 if (Value == null) {
1887 ec.Emit (OpCodes.Ldnull);
1888 return;
1892 // Use string.Empty for both literals and constants even if
1893 // it's not allowed at language level
1895 if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) {
1896 if (TypeManager.string_empty == null)
1897 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type);
1899 if (TypeManager.string_empty != null) {
1900 ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1901 return;
1905 ec.Emit (OpCodes.Ldstr, Value);
1908 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1910 // cast to object
1911 if (type != targetType)
1912 enc.Encode (type);
1914 enc.Encode (Value);
1917 public override bool IsDefaultValue {
1918 get {
1919 return Value == null;
1923 public override bool IsNegative {
1924 get {
1925 return false;
1929 public override bool IsNull {
1930 get {
1931 return IsDefaultValue;
1935 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1937 return null;
1942 // Null constant can have its own type, think of `default (Foo)'
1944 public class NullConstant : Constant
1946 public NullConstant (TypeSpec type, Location loc)
1947 : base (loc)
1949 eclass = ExprClass.Value;
1950 this.type = type;
1953 public override string AsString ()
1955 return GetSignatureForError ();
1958 public override Expression CreateExpressionTree (ResolveContext ec)
1960 if (type == InternalType.Null || type == TypeManager.object_type) {
1961 // Optimized version, also avoids referencing literal internal type
1962 Arguments args = new Arguments (1);
1963 args.Add (new Argument (this));
1964 return CreateExpressionFactoryCall (ec, "Constant", args);
1967 return base.CreateExpressionTree (ec);
1970 protected override Expression DoResolve (ResolveContext ec)
1972 return this;
1975 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1977 // Type it as string cast
1978 if (targetType == TypeManager.object_type || targetType == TypeManager.null_type)
1979 enc.Encode (TypeManager.string_type);
1981 var ac = targetType as ArrayContainer;
1982 if (ac != null) {
1983 if (ac.Rank != 1)
1984 base.EncodeAttributeValue (rc, enc, targetType);
1985 else
1986 enc.Stream.Write (uint.MaxValue);
1987 } else {
1988 enc.Stream.Write (byte.MaxValue);
1992 public override void Emit (EmitContext ec)
1994 ec.Emit (OpCodes.Ldnull);
1996 // Only to make verifier happy
1997 if (TypeManager.IsGenericParameter (type))
1998 ec.Emit (OpCodes.Unbox_Any, type);
2001 public override string ExprClassName {
2002 get {
2003 return GetSignatureForError ();
2007 public override string GetSignatureForError ()
2009 return "null";
2012 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2014 if (targetType.IsPointer) {
2015 if (IsLiteral || this is NullPointer)
2016 return new EmptyConstantCast (new NullPointer (loc), targetType);
2018 return null;
2021 // Exlude internal compiler types
2022 if (targetType == InternalType.AnonymousMethod)
2023 return null;
2025 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2026 return null;
2028 if (TypeManager.IsReferenceType (targetType))
2029 return new NullConstant (targetType, loc);
2031 if (TypeManager.IsNullableType (targetType))
2032 return Nullable.LiftedNull.Create (targetType, loc);
2034 return null;
2037 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
2039 return ConvertExplicitly (false, targetType);
2042 public override object GetValue ()
2044 return null;
2047 public override bool IsDefaultValue {
2048 get { return true; }
2051 public override bool IsNegative {
2052 get { return false; }
2055 public override bool IsNull {
2056 get { return true; }
2059 public override bool IsZeroInteger {
2060 get { return true; }
2064 /// <summary>
2065 /// The value is constant, but when emitted has a side effect. This is
2066 /// used by BitwiseAnd to ensure that the second expression is invoked
2067 /// regardless of the value of the left side.
2068 /// </summary>
2069 public class SideEffectConstant : Constant {
2070 public Constant value;
2071 Expression side_effect;
2073 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2075 this.value = value;
2076 while (side_effect is SideEffectConstant)
2077 side_effect = ((SideEffectConstant) side_effect).side_effect;
2078 this.side_effect = side_effect;
2081 public override string AsString ()
2083 return value.AsString ();
2086 protected override Expression DoResolve (ResolveContext rc)
2088 value = value.Resolve (rc);
2090 type = value.Type;
2091 eclass = ExprClass.Value;
2092 return this;
2095 public override object GetValue ()
2097 return value.GetValue ();
2100 public override void Emit (EmitContext ec)
2102 side_effect.EmitSideEffect (ec);
2103 value.Emit (ec);
2106 public override void EmitSideEffect (EmitContext ec)
2108 side_effect.EmitSideEffect (ec);
2109 value.EmitSideEffect (ec);
2112 public override bool IsDefaultValue {
2113 get { return value.IsDefaultValue; }
2116 public override bool IsNegative {
2117 get { return value.IsNegative; }
2120 public override bool IsZeroInteger {
2121 get { return value.IsZeroInteger; }
2124 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2126 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2127 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);