2010-04-15 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / constant.cs
blobb046f5579f7116c481639f5436125eff27453c18
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, Type 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, Type 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, Type 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, Type t, object v, Location loc)
101 return CreateConstantFromValue (t, v, loc).Resolve (rc);
104 public static Constant CreateConstantFromValue (Type 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 Type real_type = TypeManager.GetEnumUnderlyingType (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, Type target_type);
167 /// <summary>
168 /// Attempts to do a compile-time folding of a constant cast.
169 /// </summary>
170 public Constant TryReduce (ResolveContext ec, Type 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, Type target_type)
189 if (Type == target_type)
190 return this;
192 Constant c;
193 if (TypeManager.IsEnumType (target_type)) {
194 c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (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 (Type 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);
262 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
264 // A constant cannot be of generic type
267 public new Constant Resolve (ResolveContext rc)
269 if (eclass != ExprClass.Unresolved)
270 return this;
272 // Resolved constant has to be still a constant
273 Constant c = (Constant) DoResolve (rc);
274 if (c == null)
275 return null;
277 if ((c.eclass & ExprClass.Value) == 0) {
278 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
279 return null;
282 if (c.type == null)
283 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
285 return c;
289 public abstract class IntegralConstant : Constant {
290 protected IntegralConstant (Location loc) :
291 base (loc)
295 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
297 try {
298 ConvertExplicitly (true, target);
299 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
301 catch
303 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
304 GetValue ().ToString (), TypeManager.CSharpName (target));
308 public abstract Constant Increment ();
311 public class BoolConstant : Constant {
312 public readonly bool Value;
314 public BoolConstant (bool val, Location loc):
315 base (loc)
317 Value = val;
320 override public string AsString ()
322 return Value ? "true" : "false";
325 protected override Expression DoResolve (ResolveContext ec)
327 type = TypeManager.bool_type;
328 eclass = ExprClass.Value;
329 return this;
332 public override object GetValue ()
334 return (object) Value;
337 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
339 enc.Stream.Write (Value);
342 public override void Emit (EmitContext ec)
344 if (Value)
345 ec.ig.Emit (OpCodes.Ldc_I4_1);
346 else
347 ec.ig.Emit (OpCodes.Ldc_I4_0);
350 public override bool IsDefaultValue {
351 get {
352 return !Value;
356 public override bool IsNegative {
357 get {
358 return false;
362 public override bool IsZeroInteger {
363 get { return Value == false; }
366 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
368 return null;
373 public class ByteConstant : IntegralConstant {
374 public readonly byte Value;
376 public ByteConstant (byte v, Location loc):
377 base (loc)
379 Value = v;
382 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
384 enc.Stream.Write (Value);
387 public override void Emit (EmitContext ec)
389 IntLiteral.EmitInt (ec.ig, Value);
392 public override string AsString ()
394 return Value.ToString ();
397 protected override Expression DoResolve (ResolveContext ec)
399 type = TypeManager.byte_type;
400 eclass = ExprClass.Value;
401 return this;
404 public override object GetValue ()
406 return Value;
409 public override Constant Increment ()
411 return new ByteConstant (checked ((byte)(Value + 1)), loc);
414 public override bool IsDefaultValue {
415 get {
416 return Value == 0;
420 public override bool IsOneInteger {
421 get {
422 return Value == 1;
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 EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
489 enc.Stream.Write ((ushort) Value);
492 public override void Emit (EmitContext ec)
494 IntLiteral.EmitInt (ec.ig, Value);
497 static string descape (char c)
499 switch (c){
500 case '\a':
501 return "\\a";
502 case '\b':
503 return "\\b";
504 case '\n':
505 return "\\n";
506 case '\t':
507 return "\\t";
508 case '\v':
509 return "\\v";
510 case '\r':
511 return "\\r";
512 case '\\':
513 return "\\\\";
514 case '\f':
515 return "\\f";
516 case '\0':
517 return "\\0";
518 case '"':
519 return "\\\"";
520 case '\'':
521 return "\\\'";
523 return c.ToString ();
526 public override string AsString ()
528 return "\"" + descape (Value) + "\"";
531 public override object GetValue ()
533 return Value;
536 public override bool IsDefaultValue {
537 get {
538 return Value == 0;
542 public override bool IsNegative {
543 get {
544 return false;
548 public override bool IsZeroInteger {
549 get { return Value == '\0'; }
552 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
554 if (target_type == TypeManager.byte_type) {
555 if (in_checked_context){
556 if (Value < Byte.MinValue || Value > Byte.MaxValue)
557 throw new OverflowException ();
559 return new ByteConstant ((byte) Value, Location);
561 if (target_type == TypeManager.sbyte_type) {
562 if (in_checked_context){
563 if (Value > SByte.MaxValue)
564 throw new OverflowException ();
566 return new SByteConstant ((sbyte) Value, Location);
568 if (target_type == TypeManager.short_type) {
569 if (in_checked_context){
570 if (Value > Int16.MaxValue)
571 throw new OverflowException ();
573 return new ShortConstant ((short) Value, Location);
575 if (target_type == TypeManager.int32_type)
576 return new IntConstant ((int) Value, Location);
577 if (target_type == TypeManager.uint32_type)
578 return new UIntConstant ((uint) Value, Location);
579 if (target_type == TypeManager.int64_type)
580 return new LongConstant ((long) Value, Location);
581 if (target_type == TypeManager.uint64_type)
582 return new ULongConstant ((ulong) Value, Location);
583 if (target_type == TypeManager.float_type)
584 return new FloatConstant ((float) Value, Location);
585 if (target_type == TypeManager.double_type)
586 return new DoubleConstant ((double) Value, Location);
587 if (target_type == TypeManager.decimal_type)
588 return new DecimalConstant ((decimal) Value, Location);
590 return null;
595 public class SByteConstant : IntegralConstant {
596 public readonly sbyte Value;
598 public SByteConstant (sbyte v, Location loc):
599 base (loc)
601 Value = v;
604 protected override Expression DoResolve (ResolveContext rc)
606 type = TypeManager.sbyte_type;
607 eclass = ExprClass.Value;
608 return this;
611 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
613 enc.Stream.Write (Value);
616 public override void Emit (EmitContext ec)
618 IntLiteral.EmitInt (ec.ig, Value);
621 public override string AsString ()
623 return Value.ToString ();
626 public override object GetValue ()
628 return Value;
631 public override Constant Increment ()
633 return new SByteConstant (checked((sbyte)(Value + 1)), loc);
636 public override bool IsDefaultValue {
637 get {
638 return Value == 0;
642 public override bool IsNegative {
643 get {
644 return Value < 0;
648 public override bool IsOneInteger {
649 get {
650 return Value == 1;
654 public override bool IsZeroInteger {
655 get { return Value == 0; }
658 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
660 if (target_type == TypeManager.byte_type) {
661 if (in_checked_context && Value < 0)
662 throw new OverflowException ();
663 return new ByteConstant ((byte) Value, Location);
665 if (target_type == TypeManager.short_type)
666 return new ShortConstant ((short) Value, Location);
667 if (target_type == TypeManager.ushort_type) {
668 if (in_checked_context && Value < 0)
669 throw new OverflowException ();
670 return new UShortConstant ((ushort) Value, Location);
671 } if (target_type == TypeManager.int32_type)
672 return new IntConstant ((int) Value, Location);
673 if (target_type == TypeManager.uint32_type) {
674 if (in_checked_context && Value < 0)
675 throw new OverflowException ();
676 return new UIntConstant ((uint) Value, Location);
677 } if (target_type == TypeManager.int64_type)
678 return new LongConstant ((long) Value, Location);
679 if (target_type == TypeManager.uint64_type) {
680 if (in_checked_context && Value < 0)
681 throw new OverflowException ();
682 return new ULongConstant ((ulong) Value, Location);
684 if (target_type == TypeManager.float_type)
685 return new FloatConstant ((float) Value, Location);
686 if (target_type == TypeManager.double_type)
687 return new DoubleConstant ((double) Value, Location);
688 if (target_type == TypeManager.char_type) {
689 if (in_checked_context && Value < 0)
690 throw new OverflowException ();
691 return new CharConstant ((char) Value, Location);
693 if (target_type == TypeManager.decimal_type)
694 return new DecimalConstant ((decimal) Value, Location);
696 return null;
701 public class ShortConstant : IntegralConstant {
702 public readonly short Value;
704 public ShortConstant (short v, Location loc):
705 base (loc)
707 Value = v;
710 protected override Expression DoResolve (ResolveContext rc)
712 type = TypeManager.short_type;
713 eclass = ExprClass.Value;
714 return this;
717 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
719 enc.Stream.Write (Value);
722 public override void Emit (EmitContext ec)
724 IntLiteral.EmitInt (ec.ig, Value);
727 public override string AsString ()
729 return Value.ToString ();
732 public override object GetValue ()
734 return Value;
737 public override Constant Increment ()
739 return new ShortConstant (checked((short)(Value + 1)), loc);
742 public override bool IsDefaultValue {
743 get {
744 return Value == 0;
748 public override bool IsZeroInteger {
749 get { return Value == 0; }
752 public override bool IsNegative {
753 get {
754 return Value < 0;
758 public override bool IsOneInteger {
759 get {
760 return Value == 1;
764 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
766 if (target_type == TypeManager.byte_type) {
767 if (in_checked_context){
768 if (Value < Byte.MinValue || Value > Byte.MaxValue)
769 throw new OverflowException ();
771 return new ByteConstant ((byte) Value, Location);
773 if (target_type == TypeManager.sbyte_type) {
774 if (in_checked_context){
775 if (Value < SByte.MinValue || Value > SByte.MaxValue)
776 throw new OverflowException ();
778 return new SByteConstant ((sbyte) Value, Location);
780 if (target_type == TypeManager.ushort_type) {
781 if (in_checked_context && Value < 0)
782 throw new OverflowException ();
784 return new UShortConstant ((ushort) Value, Location);
786 if (target_type == TypeManager.int32_type)
787 return new IntConstant ((int) Value, Location);
788 if (target_type == TypeManager.uint32_type) {
789 if (in_checked_context && Value < 0)
790 throw new OverflowException ();
791 return new UIntConstant ((uint) Value, Location);
793 if (target_type == TypeManager.int64_type)
794 return new LongConstant ((long) Value, Location);
795 if (target_type == TypeManager.uint64_type) {
796 if (in_checked_context && Value < 0)
797 throw new OverflowException ();
798 return new ULongConstant ((ulong) Value, Location);
800 if (target_type == TypeManager.float_type)
801 return new FloatConstant ((float) Value, Location);
802 if (target_type == TypeManager.double_type)
803 return new DoubleConstant ((double) Value, Location);
804 if (target_type == TypeManager.char_type) {
805 if (in_checked_context){
806 if (Value < Char.MinValue)
807 throw new OverflowException ();
809 return new CharConstant ((char) Value, Location);
811 if (target_type == TypeManager.decimal_type)
812 return new DecimalConstant ((decimal) Value, Location);
814 return null;
819 public class UShortConstant : IntegralConstant {
820 public readonly ushort Value;
822 public UShortConstant (ushort v, Location loc):
823 base (loc)
825 Value = v;
828 protected override Expression DoResolve (ResolveContext rc)
830 type = TypeManager.ushort_type;
831 eclass = ExprClass.Value;
832 return this;
835 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
837 enc.Stream.Write (Value);
840 public override void Emit (EmitContext ec)
842 IntLiteral.EmitInt (ec.ig, Value);
845 public override string AsString ()
847 return Value.ToString ();
850 public override object GetValue ()
852 return Value;
855 public override Constant Increment ()
857 return new UShortConstant (checked((ushort)(Value + 1)), loc);
860 public override bool IsDefaultValue {
861 get {
862 return Value == 0;
866 public override bool IsNegative {
867 get {
868 return false;
872 public override bool IsOneInteger {
873 get {
874 return Value == 1;
878 public override bool IsZeroInteger {
879 get { return Value == 0; }
882 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
884 if (target_type == TypeManager.byte_type) {
885 if (in_checked_context){
886 if (Value > Byte.MaxValue)
887 throw new OverflowException ();
889 return new ByteConstant ((byte) Value, Location);
891 if (target_type == TypeManager.sbyte_type) {
892 if (in_checked_context){
893 if (Value > SByte.MaxValue)
894 throw new OverflowException ();
896 return new SByteConstant ((sbyte) Value, Location);
898 if (target_type == TypeManager.short_type) {
899 if (in_checked_context){
900 if (Value > Int16.MaxValue)
901 throw new OverflowException ();
903 return new ShortConstant ((short) Value, Location);
905 if (target_type == TypeManager.int32_type)
906 return new IntConstant ((int) Value, Location);
907 if (target_type == TypeManager.uint32_type)
908 return new UIntConstant ((uint) Value, Location);
909 if (target_type == TypeManager.int64_type)
910 return new LongConstant ((long) Value, Location);
911 if (target_type == TypeManager.uint64_type)
912 return new ULongConstant ((ulong) Value, Location);
913 if (target_type == TypeManager.float_type)
914 return new FloatConstant ((float) Value, Location);
915 if (target_type == TypeManager.double_type)
916 return new DoubleConstant ((double) Value, Location);
917 if (target_type == TypeManager.char_type) {
918 if (in_checked_context){
919 if (Value > Char.MaxValue)
920 throw new OverflowException ();
922 return new CharConstant ((char) Value, Location);
924 if (target_type == TypeManager.decimal_type)
925 return new DecimalConstant ((decimal) Value, Location);
927 return null;
931 public class IntConstant : IntegralConstant {
932 public readonly int Value;
934 public IntConstant (int v, Location loc):
935 base (loc)
937 Value = v;
940 protected override Expression DoResolve (ResolveContext rc)
942 type = TypeManager.int32_type;
943 eclass = ExprClass.Value;
944 return this;
947 static public void EmitInt (ILGenerator ig, int i)
949 switch (i){
950 case -1:
951 ig.Emit (OpCodes.Ldc_I4_M1);
952 break;
954 case 0:
955 ig.Emit (OpCodes.Ldc_I4_0);
956 break;
958 case 1:
959 ig.Emit (OpCodes.Ldc_I4_1);
960 break;
962 case 2:
963 ig.Emit (OpCodes.Ldc_I4_2);
964 break;
966 case 3:
967 ig.Emit (OpCodes.Ldc_I4_3);
968 break;
970 case 4:
971 ig.Emit (OpCodes.Ldc_I4_4);
972 break;
974 case 5:
975 ig.Emit (OpCodes.Ldc_I4_5);
976 break;
978 case 6:
979 ig.Emit (OpCodes.Ldc_I4_6);
980 break;
982 case 7:
983 ig.Emit (OpCodes.Ldc_I4_7);
984 break;
986 case 8:
987 ig.Emit (OpCodes.Ldc_I4_8);
988 break;
990 default:
991 if (i >= -128 && i <= 127){
992 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
993 } else
994 ig.Emit (OpCodes.Ldc_I4, i);
995 break;
999 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1001 enc.Stream.Write (Value);
1004 public override void Emit (EmitContext ec)
1006 EmitInt (ec.ig, Value);
1009 public override string AsString ()
1011 return Value.ToString ();
1014 public override object GetValue ()
1016 return Value;
1019 public override Constant Increment ()
1021 return new IntConstant (checked(Value + 1), loc);
1024 public override bool IsDefaultValue {
1025 get {
1026 return Value == 0;
1030 public override bool IsNegative {
1031 get {
1032 return Value < 0;
1036 public override bool IsOneInteger {
1037 get {
1038 return Value == 1;
1042 public override bool IsZeroInteger {
1043 get { return Value == 0; }
1046 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1048 if (target_type == TypeManager.byte_type) {
1049 if (in_checked_context){
1050 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1051 throw new OverflowException ();
1053 return new ByteConstant ((byte) Value, Location);
1055 if (target_type == TypeManager.sbyte_type) {
1056 if (in_checked_context){
1057 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1058 throw new OverflowException ();
1060 return new SByteConstant ((sbyte) Value, Location);
1062 if (target_type == TypeManager.short_type) {
1063 if (in_checked_context){
1064 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1065 throw new OverflowException ();
1067 return new ShortConstant ((short) Value, Location);
1069 if (target_type == TypeManager.ushort_type) {
1070 if (in_checked_context){
1071 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1072 throw new OverflowException ();
1074 return new UShortConstant ((ushort) Value, Location);
1076 if (target_type == TypeManager.uint32_type) {
1077 if (in_checked_context){
1078 if (Value < UInt32.MinValue)
1079 throw new OverflowException ();
1081 return new UIntConstant ((uint) Value, Location);
1083 if (target_type == TypeManager.int64_type)
1084 return new LongConstant ((long) Value, Location);
1085 if (target_type == TypeManager.uint64_type) {
1086 if (in_checked_context && Value < 0)
1087 throw new OverflowException ();
1088 return new ULongConstant ((ulong) Value, Location);
1090 if (target_type == TypeManager.float_type)
1091 return new FloatConstant ((float) Value, Location);
1092 if (target_type == TypeManager.double_type)
1093 return new DoubleConstant ((double) Value, Location);
1094 if (target_type == TypeManager.char_type) {
1095 if (in_checked_context){
1096 if (Value < Char.MinValue || Value > Char.MaxValue)
1097 throw new OverflowException ();
1099 return new CharConstant ((char) Value, Location);
1101 if (target_type == TypeManager.decimal_type)
1102 return new DecimalConstant ((decimal) Value, Location);
1104 return null;
1107 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
1109 if (this.type == type)
1110 return this;
1112 Constant c = TryImplicitIntConversion (type);
1113 if (c != null)
1114 return c.Resolve (rc);
1116 return base.ConvertImplicitly (rc, type);
1119 /// <summary>
1120 /// Attempts to perform an implicit constant conversion of the IntConstant
1121 /// into a different data type using casts (See Implicit Constant
1122 /// Expression Conversions)
1123 /// </summary>
1124 Constant TryImplicitIntConversion (Type target_type)
1126 if (target_type == TypeManager.sbyte_type) {
1127 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1128 return new SByteConstant ((sbyte) Value, loc);
1130 else if (target_type == TypeManager.byte_type) {
1131 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1132 return new ByteConstant ((byte) Value, loc);
1134 else if (target_type == TypeManager.short_type) {
1135 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1136 return new ShortConstant ((short) Value, loc);
1138 else if (target_type == TypeManager.ushort_type) {
1139 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1140 return new UShortConstant ((ushort) Value, loc);
1142 else if (target_type == TypeManager.uint32_type) {
1143 if (Value >= 0)
1144 return new UIntConstant ((uint) Value, loc);
1146 else if (target_type == TypeManager.uint64_type) {
1148 // we can optimize this case: a positive int32
1149 // always fits on a uint64. But we need an opcode
1150 // to do it.
1152 if (Value >= 0)
1153 return new ULongConstant ((ulong) Value, loc);
1155 else if (target_type == TypeManager.double_type)
1156 return new DoubleConstant ((double) Value, loc);
1157 else if (target_type == TypeManager.float_type)
1158 return new FloatConstant ((float) Value, loc);
1160 return null;
1164 public class UIntConstant : IntegralConstant {
1165 public readonly uint Value;
1167 public UIntConstant (uint v, Location loc):
1168 base (loc)
1170 Value = v;
1173 protected override Expression DoResolve (ResolveContext rc)
1175 type = TypeManager.uint32_type;
1176 eclass = ExprClass.Value;
1177 return this;
1180 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1182 enc.Stream.Write (Value);
1185 public override void Emit (EmitContext ec)
1187 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
1190 public override string AsString ()
1192 return Value.ToString ();
1195 public override object GetValue ()
1197 return Value;
1200 public override Constant Increment ()
1202 return new UIntConstant (checked(Value + 1), loc);
1205 public override bool IsDefaultValue {
1206 get {
1207 return Value == 0;
1211 public override bool IsNegative {
1212 get {
1213 return false;
1217 public override bool IsOneInteger {
1218 get {
1219 return Value == 1;
1223 public override bool IsZeroInteger {
1224 get { return Value == 0; }
1227 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1229 if (target_type == TypeManager.byte_type) {
1230 if (in_checked_context){
1231 if (Value < Char.MinValue || Value > Char.MaxValue)
1232 throw new OverflowException ();
1234 return new ByteConstant ((byte) Value, Location);
1236 if (target_type == TypeManager.sbyte_type) {
1237 if (in_checked_context){
1238 if (Value > SByte.MaxValue)
1239 throw new OverflowException ();
1241 return new SByteConstant ((sbyte) Value, Location);
1243 if (target_type == TypeManager.short_type) {
1244 if (in_checked_context){
1245 if (Value > Int16.MaxValue)
1246 throw new OverflowException ();
1248 return new ShortConstant ((short) Value, Location);
1250 if (target_type == TypeManager.ushort_type) {
1251 if (in_checked_context){
1252 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1253 throw new OverflowException ();
1255 return new UShortConstant ((ushort) Value, Location);
1257 if (target_type == TypeManager.int32_type) {
1258 if (in_checked_context){
1259 if (Value > Int32.MaxValue)
1260 throw new OverflowException ();
1262 return new IntConstant ((int) Value, Location);
1264 if (target_type == TypeManager.int64_type)
1265 return new LongConstant ((long) Value, Location);
1266 if (target_type == TypeManager.uint64_type)
1267 return new ULongConstant ((ulong) Value, Location);
1268 if (target_type == TypeManager.float_type)
1269 return new FloatConstant ((float) Value, Location);
1270 if (target_type == TypeManager.double_type)
1271 return new DoubleConstant ((double) Value, Location);
1272 if (target_type == TypeManager.char_type) {
1273 if (in_checked_context){
1274 if (Value < Char.MinValue || Value > Char.MaxValue)
1275 throw new OverflowException ();
1277 return new CharConstant ((char) Value, Location);
1279 if (target_type == TypeManager.decimal_type)
1280 return new DecimalConstant ((decimal) Value, Location);
1282 return null;
1287 public class LongConstant : IntegralConstant {
1288 public readonly long Value;
1290 public LongConstant (long v, Location loc):
1291 base (loc)
1293 Value = v;
1296 protected override Expression DoResolve (ResolveContext rc)
1298 type = TypeManager.int64_type;
1299 eclass = ExprClass.Value;
1300 return this;
1303 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1305 enc.Stream.Write (Value);
1308 public override void Emit (EmitContext ec)
1310 EmitLong (ec.ig, Value);
1313 static public void EmitLong (ILGenerator ig, long l)
1315 if (l >= int.MinValue && l <= int.MaxValue) {
1316 IntLiteral.EmitInt (ig, unchecked ((int) l));
1317 ig.Emit (OpCodes.Conv_I8);
1318 return;
1321 if (l >= 0 && l <= uint.MaxValue) {
1322 IntLiteral.EmitInt (ig, unchecked ((int) l));
1323 ig.Emit (OpCodes.Conv_U8);
1324 return;
1327 ig.Emit (OpCodes.Ldc_I8, l);
1330 public override string AsString ()
1332 return Value.ToString ();
1335 public override object GetValue ()
1337 return Value;
1340 public override Constant Increment ()
1342 return new LongConstant (checked(Value + 1), loc);
1345 public override bool IsDefaultValue {
1346 get {
1347 return Value == 0;
1351 public override bool IsNegative {
1352 get {
1353 return Value < 0;
1357 public override bool IsOneInteger {
1358 get {
1359 return Value == 1;
1363 public override bool IsZeroInteger {
1364 get { return Value == 0; }
1367 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1369 if (target_type == TypeManager.byte_type) {
1370 if (in_checked_context){
1371 if (Value < Byte.MinValue || Value > Byte.MaxValue)
1372 throw new OverflowException ();
1374 return new ByteConstant ((byte) Value, Location);
1376 if (target_type == TypeManager.sbyte_type) {
1377 if (in_checked_context){
1378 if (Value < SByte.MinValue || Value > SByte.MaxValue)
1379 throw new OverflowException ();
1381 return new SByteConstant ((sbyte) Value, Location);
1383 if (target_type == TypeManager.short_type) {
1384 if (in_checked_context){
1385 if (Value < Int16.MinValue || Value > Int16.MaxValue)
1386 throw new OverflowException ();
1388 return new ShortConstant ((short) Value, Location);
1390 if (target_type == TypeManager.ushort_type) {
1391 if (in_checked_context){
1392 if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1393 throw new OverflowException ();
1395 return new UShortConstant ((ushort) Value, Location);
1397 if (target_type == TypeManager.int32_type) {
1398 if (in_checked_context){
1399 if (Value < Int32.MinValue || Value > Int32.MaxValue)
1400 throw new OverflowException ();
1402 return new IntConstant ((int) Value, Location);
1404 if (target_type == TypeManager.uint32_type) {
1405 if (in_checked_context){
1406 if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1407 throw new OverflowException ();
1409 return new UIntConstant ((uint) Value, Location);
1411 if (target_type == TypeManager.uint64_type) {
1412 if (in_checked_context && Value < 0)
1413 throw new OverflowException ();
1414 return new ULongConstant ((ulong) Value, Location);
1416 if (target_type == TypeManager.float_type)
1417 return new FloatConstant ((float) Value, Location);
1418 if (target_type == TypeManager.double_type)
1419 return new DoubleConstant ((double) Value, Location);
1420 if (target_type == TypeManager.char_type) {
1421 if (in_checked_context){
1422 if (Value < Char.MinValue || Value > Char.MaxValue)
1423 throw new OverflowException ();
1425 return new CharConstant ((char) Value, Location);
1427 if (target_type == TypeManager.decimal_type)
1428 return new DecimalConstant ((decimal) Value, Location);
1430 return null;
1433 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
1435 if (Value >= 0 && type == TypeManager.uint64_type) {
1436 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1439 return base.ConvertImplicitly (rc, type);
1443 public class ULongConstant : IntegralConstant {
1444 public readonly ulong Value;
1446 public ULongConstant (ulong v, Location loc):
1447 base (loc)
1449 Value = v;
1452 protected override Expression DoResolve (ResolveContext rc)
1454 type = TypeManager.uint64_type;
1455 eclass = ExprClass.Value;
1456 return this;
1459 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1461 enc.Stream.Write (Value);
1464 public override void Emit (EmitContext ec)
1466 ILGenerator ig = ec.ig;
1468 LongLiteral.EmitLong (ig, unchecked ((long) Value));
1471 public override string AsString ()
1473 return Value.ToString ();
1476 public override object GetValue ()
1478 return Value;
1481 public override Constant Increment ()
1483 return new ULongConstant (checked(Value + 1), loc);
1486 public override bool IsDefaultValue {
1487 get {
1488 return Value == 0;
1492 public override bool IsNegative {
1493 get {
1494 return false;
1498 public override bool IsOneInteger {
1499 get {
1500 return Value == 1;
1504 public override bool IsZeroInteger {
1505 get { return Value == 0; }
1508 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1510 if (target_type == TypeManager.byte_type) {
1511 if (in_checked_context && Value > Byte.MaxValue)
1512 throw new OverflowException ();
1513 return new ByteConstant ((byte) Value, Location);
1515 if (target_type == TypeManager.sbyte_type) {
1516 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1517 throw new OverflowException ();
1518 return new SByteConstant ((sbyte) Value, Location);
1520 if (target_type == TypeManager.short_type) {
1521 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1522 throw new OverflowException ();
1523 return new ShortConstant ((short) Value, Location);
1525 if (target_type == TypeManager.ushort_type) {
1526 if (in_checked_context && Value > UInt16.MaxValue)
1527 throw new OverflowException ();
1528 return new UShortConstant ((ushort) Value, Location);
1530 if (target_type == TypeManager.int32_type) {
1531 if (in_checked_context && Value > UInt32.MaxValue)
1532 throw new OverflowException ();
1533 return new IntConstant ((int) Value, Location);
1535 if (target_type == TypeManager.uint32_type) {
1536 if (in_checked_context && Value > UInt32.MaxValue)
1537 throw new OverflowException ();
1538 return new UIntConstant ((uint) Value, Location);
1540 if (target_type == TypeManager.int64_type) {
1541 if (in_checked_context && Value > Int64.MaxValue)
1542 throw new OverflowException ();
1543 return new LongConstant ((long) Value, Location);
1545 if (target_type == TypeManager.float_type)
1546 return new FloatConstant ((float) Value, Location);
1547 if (target_type == TypeManager.double_type)
1548 return new DoubleConstant ((double) Value, Location);
1549 if (target_type == TypeManager.char_type) {
1550 if (in_checked_context && Value > Char.MaxValue)
1551 throw new OverflowException ();
1552 return new CharConstant ((char) Value, Location);
1554 if (target_type == TypeManager.decimal_type)
1555 return new DecimalConstant ((decimal) Value, Location);
1557 return null;
1562 public class FloatConstant : Constant {
1563 public float Value;
1565 public FloatConstant (float v, Location loc):
1566 base (loc)
1568 Value = v;
1571 protected override Expression DoResolve (ResolveContext rc)
1573 type = TypeManager.float_type;
1574 eclass = ExprClass.Value;
1575 return this;
1578 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1580 enc.Stream.Write (Value);
1583 public override void Emit (EmitContext ec)
1585 ec.ig.Emit (OpCodes.Ldc_R4, Value);
1588 public override string AsString ()
1590 return Value.ToString ();
1593 public override object GetValue ()
1595 return Value;
1598 public override bool IsDefaultValue {
1599 get {
1600 return Value == 0;
1604 public override bool IsNegative {
1605 get {
1606 return Value < 0;
1610 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1612 if (target_type == TypeManager.byte_type) {
1613 if (in_checked_context){
1614 if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1615 throw new OverflowException ();
1617 return new ByteConstant ((byte) Value, Location);
1619 if (target_type == TypeManager.sbyte_type) {
1620 if (in_checked_context){
1621 if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1622 throw new OverflowException ();
1624 return new SByteConstant ((sbyte) Value, Location);
1626 if (target_type == TypeManager.short_type) {
1627 if (in_checked_context){
1628 if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1629 throw new OverflowException ();
1631 return new ShortConstant ((short) Value, Location);
1633 if (target_type == TypeManager.ushort_type) {
1634 if (in_checked_context){
1635 if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1636 throw new OverflowException ();
1638 return new UShortConstant ((ushort) Value, Location);
1640 if (target_type == TypeManager.int32_type) {
1641 if (in_checked_context){
1642 if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1643 throw new OverflowException ();
1645 return new IntConstant ((int) Value, Location);
1647 if (target_type == TypeManager.uint32_type) {
1648 if (in_checked_context){
1649 if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1650 throw new OverflowException ();
1652 return new UIntConstant ((uint) Value, Location);
1654 if (target_type == TypeManager.int64_type) {
1655 if (in_checked_context){
1656 if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1657 throw new OverflowException ();
1659 return new LongConstant ((long) Value, Location);
1661 if (target_type == TypeManager.uint64_type) {
1662 if (in_checked_context){
1663 if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1664 throw new OverflowException ();
1666 return new ULongConstant ((ulong) Value, Location);
1668 if (target_type == TypeManager.double_type)
1669 return new DoubleConstant ((double) Value, Location);
1670 if (target_type == TypeManager.char_type) {
1671 if (in_checked_context){
1672 if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1673 throw new OverflowException ();
1675 return new CharConstant ((char) Value, Location);
1677 if (target_type == TypeManager.decimal_type)
1678 return new DecimalConstant ((decimal) Value, Location);
1680 return null;
1685 public class DoubleConstant : Constant {
1686 public double Value;
1688 public DoubleConstant (double v, Location loc):
1689 base (loc)
1691 Value = v;
1694 protected override Expression DoResolve (ResolveContext rc)
1696 type = TypeManager.double_type;
1697 eclass = ExprClass.Value;
1698 return this;
1701 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1703 enc.Stream.Write (Value);
1706 public override void Emit (EmitContext ec)
1708 ec.ig.Emit (OpCodes.Ldc_R8, Value);
1711 public override string AsString ()
1713 return Value.ToString ();
1716 public override object GetValue ()
1718 return Value;
1721 public override bool IsDefaultValue {
1722 get {
1723 return Value == 0;
1727 public override bool IsNegative {
1728 get {
1729 return Value < 0;
1733 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1735 if (target_type == TypeManager.byte_type) {
1736 if (in_checked_context){
1737 if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1738 throw new OverflowException ();
1740 return new ByteConstant ((byte) Value, Location);
1742 if (target_type == TypeManager.sbyte_type) {
1743 if (in_checked_context){
1744 if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1745 throw new OverflowException ();
1747 return new SByteConstant ((sbyte) Value, Location);
1749 if (target_type == TypeManager.short_type) {
1750 if (in_checked_context){
1751 if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1752 throw new OverflowException ();
1754 return new ShortConstant ((short) Value, Location);
1756 if (target_type == TypeManager.ushort_type) {
1757 if (in_checked_context){
1758 if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1759 throw new OverflowException ();
1761 return new UShortConstant ((ushort) Value, Location);
1763 if (target_type == TypeManager.int32_type) {
1764 if (in_checked_context){
1765 if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1766 throw new OverflowException ();
1768 return new IntConstant ((int) Value, Location);
1770 if (target_type == TypeManager.uint32_type) {
1771 if (in_checked_context){
1772 if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1773 throw new OverflowException ();
1775 return new UIntConstant ((uint) Value, Location);
1777 if (target_type == TypeManager.int64_type) {
1778 if (in_checked_context){
1779 if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1780 throw new OverflowException ();
1782 return new LongConstant ((long) Value, Location);
1784 if (target_type == TypeManager.uint64_type) {
1785 if (in_checked_context){
1786 if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1787 throw new OverflowException ();
1789 return new ULongConstant ((ulong) Value, Location);
1791 if (target_type == TypeManager.float_type)
1792 return new FloatConstant ((float) Value, Location);
1793 if (target_type == TypeManager.char_type) {
1794 if (in_checked_context){
1795 if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1796 throw new OverflowException ();
1798 return new CharConstant ((char) Value, Location);
1800 if (target_type == TypeManager.decimal_type)
1801 return new DecimalConstant ((decimal) Value, Location);
1803 return null;
1808 public class DecimalConstant : Constant {
1809 public readonly decimal Value;
1811 public DecimalConstant (decimal d, Location loc):
1812 base (loc)
1814 Value = d;
1817 override public string AsString ()
1819 return Value.ToString () + "M";
1822 protected override Expression DoResolve (ResolveContext rc)
1824 type = TypeManager.decimal_type;
1825 eclass = ExprClass.Value;
1826 return this;
1829 public override object GetValue ()
1831 return (object) Value;
1834 public override void Emit (EmitContext ec)
1836 ILGenerator ig = ec.ig;
1838 int [] words = decimal.GetBits (Value);
1839 int power = (words [3] >> 16) & 0xff;
1841 if (power == 0) {
1842 if (Value <= int.MaxValue && Value >= int.MinValue) {
1843 if (TypeManager.void_decimal_ctor_int_arg == null) {
1844 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1845 TypeManager.decimal_type, loc, TypeManager.int32_type);
1847 if (TypeManager.void_decimal_ctor_int_arg == null)
1848 return;
1851 IntConstant.EmitInt (ig, (int) Value);
1852 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1853 return;
1856 if (Value <= long.MaxValue && Value >= long.MinValue) {
1857 if (TypeManager.void_decimal_ctor_long_arg == null) {
1858 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1859 TypeManager.decimal_type, loc, TypeManager.int64_type);
1861 if (TypeManager.void_decimal_ctor_long_arg == null)
1862 return;
1865 LongConstant.EmitLong (ig, (long) Value);
1866 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1867 return;
1871 IntConstant.EmitInt (ig, words [0]);
1872 IntConstant.EmitInt (ig, words [1]);
1873 IntConstant.EmitInt (ig, words [2]);
1875 // sign
1876 IntConstant.EmitInt (ig, words [3] >> 31);
1878 // power
1879 IntConstant.EmitInt (ig, power);
1881 if (TypeManager.void_decimal_ctor_five_args == null) {
1882 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1883 TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1884 TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1886 if (TypeManager.void_decimal_ctor_five_args == null)
1887 return;
1890 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1893 public override bool IsDefaultValue {
1894 get {
1895 return Value == 0;
1899 public override bool IsNegative {
1900 get {
1901 return Value < 0;
1905 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1907 if (target_type == TypeManager.sbyte_type)
1908 return new SByteConstant ((sbyte)Value, loc);
1909 if (target_type == TypeManager.byte_type)
1910 return new ByteConstant ((byte)Value, loc);
1911 if (target_type == TypeManager.short_type)
1912 return new ShortConstant ((short)Value, loc);
1913 if (target_type == TypeManager.ushort_type)
1914 return new UShortConstant ((ushort)Value, loc);
1915 if (target_type == TypeManager.int32_type)
1916 return new IntConstant ((int)Value, loc);
1917 if (target_type == TypeManager.uint32_type)
1918 return new UIntConstant ((uint)Value, loc);
1919 if (target_type == TypeManager.int64_type)
1920 return new LongConstant ((long)Value, loc);
1921 if (target_type == TypeManager.uint64_type)
1922 return new ULongConstant ((ulong)Value, loc);
1923 if (target_type == TypeManager.char_type)
1924 return new CharConstant ((char)Value, loc);
1925 if (target_type == TypeManager.float_type)
1926 return new FloatConstant ((float)Value, loc);
1927 if (target_type == TypeManager.double_type)
1928 return new DoubleConstant ((double)Value, loc);
1930 return null;
1935 public class StringConstant : Constant {
1936 public readonly string Value;
1938 public StringConstant (string s, Location loc):
1939 base (loc)
1941 Value = s;
1944 // FIXME: Escape the string.
1945 override public string AsString ()
1947 return "\"" + Value + "\"";
1950 protected override Expression DoResolve (ResolveContext rc)
1952 type = TypeManager.string_type;
1953 eclass = ExprClass.Value;
1954 return this;
1957 public override object GetValue ()
1959 return Value;
1962 public override void Emit (EmitContext ec)
1964 if (Value == null) {
1965 ec.ig.Emit (OpCodes.Ldnull);
1966 return;
1970 // Use string.Empty for both literals and constants even if
1971 // it's not allowed at language level
1973 if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) {
1974 if (TypeManager.string_empty == null)
1975 TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc);
1977 if (TypeManager.string_empty != null) {
1978 ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1979 return;
1983 ec.ig.Emit (OpCodes.Ldstr, Value);
1986 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
1988 // cast to object
1989 if (type != targetType)
1990 enc.Encode (type);
1992 enc.Encode (Value);
1995 public override bool IsDefaultValue {
1996 get {
1997 return Value == null;
2001 public override bool IsNegative {
2002 get {
2003 return false;
2007 public override bool IsNull {
2008 get {
2009 return IsDefaultValue;
2013 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
2015 return null;
2020 // Null constant can have its own type, think of `default (Foo)'
2022 public class NullConstant : Constant
2024 public NullConstant (Type type, Location loc)
2025 : base (loc)
2027 eclass = ExprClass.Value;
2028 this.type = type;
2031 public override string AsString ()
2033 return GetSignatureForError ();
2036 protected override Expression DoResolve (ResolveContext ec)
2038 return this;
2041 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, Type targetType)
2043 // Type it as string cast
2044 if (targetType == TypeManager.object_type || targetType == TypeManager.null_type)
2045 enc.Encode (TypeManager.string_type);
2047 if (targetType.IsArray) {
2048 if (targetType.GetArrayRank () != 1)
2049 base.EncodeAttributeValue (rc, enc, targetType);
2050 else
2051 enc.Stream.Write (uint.MaxValue);
2052 } else {
2053 enc.Stream.Write (byte.MaxValue);
2057 public override void Emit (EmitContext ec)
2059 ec.ig.Emit (OpCodes.Ldnull);
2061 // Only to make verifier happy
2062 if (TypeManager.IsGenericParameter (type))
2063 ec.ig.Emit (OpCodes.Unbox_Any, type);
2066 public override string ExprClassName {
2067 get {
2068 return GetSignatureForError ();
2072 public override string GetSignatureForError ()
2074 return "null";
2077 public override Constant ConvertExplicitly (bool inCheckedContext, Type targetType)
2079 if (targetType.IsPointer) {
2080 if (IsLiteral || this is NullPointer)
2081 return new EmptyConstantCast (new NullPointer (loc), targetType);
2083 return null;
2086 // Exlude internal compiler types
2087 if (targetType == InternalType.AnonymousMethod)
2088 return null;
2090 if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2091 return null;
2093 if (TypeManager.IsReferenceType (targetType))
2094 return new NullConstant (targetType, loc);
2096 if (TypeManager.IsNullableType (targetType))
2097 return Nullable.LiftedNull.Create (targetType, loc);
2099 return null;
2102 public override Constant ConvertImplicitly (ResolveContext rc, Type targetType)
2104 return ConvertExplicitly (false, targetType);
2107 public override object GetValue ()
2109 return null;
2112 public override bool IsDefaultValue {
2113 get { return true; }
2116 public override bool IsNegative {
2117 get { return false; }
2120 public override bool IsNull {
2121 get { return true; }
2124 public override bool IsZeroInteger {
2125 get { return true; }
2128 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2130 type = storey.MutateType (type);
2134 /// <summary>
2135 /// The value is constant, but when emitted has a side effect. This is
2136 /// used by BitwiseAnd to ensure that the second expression is invoked
2137 /// regardless of the value of the left side.
2138 /// </summary>
2139 public class SideEffectConstant : Constant {
2140 public Constant value;
2141 Expression side_effect;
2143 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2145 this.value = value;
2146 while (side_effect is SideEffectConstant)
2147 side_effect = ((SideEffectConstant) side_effect).side_effect;
2148 this.side_effect = side_effect;
2151 public override string AsString ()
2153 return value.AsString ();
2156 protected override Expression DoResolve (ResolveContext rc)
2158 value = value.Resolve (rc);
2160 type = value.Type;
2161 eclass = ExprClass.Value;
2162 return this;
2165 public override object GetValue ()
2167 return value.GetValue ();
2170 public override void Emit (EmitContext ec)
2172 side_effect.EmitSideEffect (ec);
2173 value.Emit (ec);
2176 public override void EmitSideEffect (EmitContext ec)
2178 side_effect.EmitSideEffect (ec);
2179 value.EmitSideEffect (ec);
2182 public override bool IsDefaultValue {
2183 get { return value.IsDefaultValue; }
2186 public override bool IsNegative {
2187 get { return value.IsNegative; }
2190 public override bool IsZeroInteger {
2191 get { return value.IsZeroInteger; }
2194 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
2196 Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2197 return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);