Disable unification into current assembly, it's not fully implemented yet
[mono.git] / mcs / mcs / constant.cs
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.
10 //
11
12 using System;
13
14 #if STATIC
15 using IKVM.Reflection.Emit;
16 #else
17 using System.Reflection.Emit;
18 #endif
19
20 namespace Mono.CSharp {
21
22         /// <summary>
23         ///   Base class for constants and literals.
24         /// </summary>
25         public abstract class Constant : Expression {
26
27                 protected Constant (Location loc)
28                 {
29                         this.loc = loc;
30                 }
31
32                 /// <remarks>
33                 ///   This is different from ToString in that ToString
34                 ///   is supposed to be there for debugging purposes,
35                 ///   and is not guaranteed to be useful for anything else,
36                 ///   AsString() will provide something that can be used
37                 ///   for round-tripping C# code.  Maybe it can be used
38                 ///   for IL assembly as well.
39                 /// </remarks>
40                 public abstract string AsString ();
41
42                 override public string ToString ()
43                 {
44                         return this.GetType ().Name + " (" + AsString () + ")";
45                 }
46
47                 /// <summary>
48                 ///  This is used to obtain the actual value of the literal
49                 ///  cast into an object.
50                 /// </summary>
51                 public abstract object GetValue ();
52
53 #if !STATIC
54                 //
55                 // Returns an object value which is typed to contant type
56                 //
57                 public virtual object GetTypedValue ()
58                 {
59                         return GetValue ();
60                 }
61 #endif
62
63                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
64                 {
65                         if (!expl && IsLiteral && 
66                                 (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) &&
67                                 (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) {
68                                 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
69                                         AsString (), TypeManager.CSharpName (target));
70                         } else {
71                                 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
72                         }
73                 }
74
75                 public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc)
76                 {
77                         Constant c = ConvertImplicitly (ec, type);
78                         if (c == null)
79                                 Error_ValueCannotBeConverted (ec, loc, type, false);
80
81                         return c;
82                 }
83
84                 public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
85                 {
86                         if (this.type == type)
87                                 return this;
88
89                         if (Convert.ImplicitNumericConversion (this, type) == null) 
90                                 return null;
91
92                         bool fail;                      
93                         object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
94                         if (fail){
95                                 //
96                                 // We should always catch the error before this is ever
97                                 // reached, by calling Convert.ImplicitStandardConversionExists
98                                 //
99                                 throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
100                                   TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
101                         }
102
103                         return CreateConstant (rc, type, constant_value, loc);
104                 }
105
106                 //
107                 //  Returns a constant instance based on Type
108                 //
109                 public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc)
110                 {
111                         return CreateConstantFromValue (t, v, loc).Resolve (rc);
112                 }
113
114                 public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
115                 {
116                         if (t == TypeManager.int32_type)
117                                 return new IntConstant ((int) v, loc);
118                         if (t == TypeManager.string_type)
119                                 return new StringConstant ((string) v, loc);
120                         if (t == TypeManager.uint32_type)
121                                 return new UIntConstant ((uint) v, loc);
122                         if (t == TypeManager.int64_type)
123                                 return new LongConstant ((long) v, loc);
124                         if (t == TypeManager.uint64_type)
125                                 return new ULongConstant ((ulong) v, loc);
126                         if (t == TypeManager.float_type)
127                                 return new FloatConstant ((float) v, loc);
128                         if (t == TypeManager.double_type)
129                                 return new DoubleConstant ((double) v, loc);
130                         if (t == TypeManager.short_type)
131                                 return new ShortConstant ((short)v, loc);
132                         if (t == TypeManager.ushort_type)
133                                 return new UShortConstant ((ushort)v, loc);
134                         if (t == TypeManager.sbyte_type)
135                                 return new SByteConstant ((sbyte)v, loc);
136                         if (t == TypeManager.byte_type)
137                                 return new ByteConstant ((byte)v, loc);
138                         if (t == TypeManager.char_type)
139                                 return new CharConstant ((char)v, loc);
140                         if (t == TypeManager.bool_type)
141                                 return new BoolConstant ((bool) v, loc);
142                         if (t == TypeManager.decimal_type)
143                                 return new DecimalConstant ((decimal) v, loc);
144                         if (TypeManager.IsEnumType (t)) {
145                                 var real_type = EnumSpec.GetUnderlyingType (t);
146                                 return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t);
147                         }
148                         if (v == null) {
149                                 if (TypeManager.IsNullableType (t))
150                                         return Nullable.LiftedNull.Create (t, loc);
151
152                                 if (TypeManager.IsReferenceType (t))
153                                         return new NullConstant (t, loc);
154                         }
155
156                         throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
157                                 v, TypeManager.CSharpName (t));
158                 }
159
160                 public override Expression CreateExpressionTree (ResolveContext ec)
161                 {
162                         Arguments args = new Arguments (2);
163                         args.Add (new Argument (this));
164                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
165
166                         return CreateExpressionFactoryCall (ec, "Constant", args);
167                 }
168
169
170                 /// <summary>
171                 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
172                 /// It throws OverflowException 
173                 /// </summary>
174                 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
175                 public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type);
176
177                 /// <summary>
178                 ///   Attempts to do a compile-time folding of a constant cast.
179                 /// </summary>
180                 public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
181                 {
182                         try {
183                                 return TryReduce (ec, target_type);
184                         }
185                         catch (OverflowException) {
186                                 if (ec.ConstantCheckState) {                            
187                                         ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
188                                                 GetValue ().ToString (), TypeManager.CSharpName (target_type));
189                                 } else {
190                                         Error_ValueCannotBeConverted (ec, loc, target_type, false);
191                                 }
192
193                                 return New.Constantify (target_type, loc).Resolve (ec);
194                         }
195                 }
196
197                 Constant TryReduce (ResolveContext ec, TypeSpec target_type)
198                 {
199                         if (Type == target_type)
200                                 return this;
201
202                         Constant c;
203                         if (TypeManager.IsEnumType (target_type)) {
204                                 c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
205                                 if (c == null)
206                                         return null;
207
208                                 return new EnumConstant (c, target_type).Resolve (ec);
209                         }
210
211                         c = ConvertExplicitly (ec.ConstantCheckState, target_type);
212                         if (c != null)
213                                 c = c.Resolve (ec);
214
215                         return c;
216                 }
217
218                 /// <summary>
219                 /// Need to pass type as the constant can require a boxing
220                 /// and in such case no optimization is possible
221                 /// </summary>
222                 public bool IsDefaultInitializer (TypeSpec type)
223                 {
224                         if (type == Type)
225                                 return IsDefaultValue;
226
227                         return this is NullLiteral;
228                 }
229
230                 public abstract bool IsDefaultValue {
231                         get;
232                 }
233
234                 public abstract bool IsNegative {
235                         get;
236                 }
237
238                 //
239                 // When constant is declared as literal
240                 //
241                 public virtual bool IsLiteral {
242                         get { return false; }
243                 }
244                 
245                 public virtual bool IsOneInteger {
246                         get { return false; }
247                 }               
248
249                 //
250                 // Returns true iff 1) the stack type of this is one of Object, 
251                 // int32, int64 and 2) this == 0 or this == null.
252                 //
253                 public virtual bool IsZeroInteger {
254                         get { return false; }
255                 }
256
257                 public override void EmitSideEffect (EmitContext ec)
258                 {
259                         // do nothing
260                 }
261
262                 public sealed override Expression Clone (CloneContext clonectx)
263                 {
264                         // No cloning is not needed for constants
265                         return this;
266                 }
267
268                 protected override void CloneTo (CloneContext clonectx, Expression target)
269                 {
270                         throw new NotSupportedException ("should not be reached");
271                 }
272
273                 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
274                 {
275 #if STATIC
276                         return base.MakeExpression (ctx);
277 #else
278                         return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ());
279 #endif
280                 }
281
282                 public new Constant Resolve (ResolveContext rc)
283                 {
284                         if (eclass != ExprClass.Unresolved)
285                                 return this;
286
287                         // Resolved constant has to be still a constant
288                         Constant c = (Constant) DoResolve (rc);
289                         if (c == null)
290                                 return null;
291
292                         if ((c.eclass & ExprClass.Value) == 0) {
293                                 c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
294                                 return null;
295                         }
296
297                         if (c.type == null)
298                                 throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ());
299
300                         return c;
301                 }
302         }
303
304         public abstract class IntegralConstant : Constant
305         {
306                 protected IntegralConstant (Location loc) :
307                         base (loc)
308                 {
309                 }
310
311                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
312                 {
313                         try {
314                                 ConvertExplicitly (true, target);
315                                 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
316                         }
317                         catch
318                         {
319                                 ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
320                                         GetValue ().ToString (), TypeManager.CSharpName (target));
321                         }
322                 }
323                 
324                 public abstract Constant Increment ();
325         }
326         
327         public class BoolConstant : Constant {
328                 public readonly bool Value;
329                 
330                 public BoolConstant (bool val, Location loc):
331                         base (loc)
332                 {
333                         Value = val;
334                 }
335
336                 override public string AsString ()
337                 {
338                         return Value ? "true" : "false";
339                 }
340
341                 protected override Expression DoResolve (ResolveContext ec)
342                 {
343                         type = TypeManager.bool_type;
344                         eclass = ExprClass.Value;
345                         return this;
346                 }
347
348                 public override object GetValue ()
349                 {
350                         return (object) Value;
351                 }
352
353                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
354                 {
355                         enc.Stream.Write (Value);
356                 }
357                 
358                 public override void Emit (EmitContext ec)
359                 {
360                         if (Value)
361                                 ec.Emit (OpCodes.Ldc_I4_1);
362                         else
363                                 ec.Emit (OpCodes.Ldc_I4_0);
364                 }
365
366                 public override bool IsDefaultValue {
367                         get {
368                                 return !Value;
369                         }
370                 }
371
372                 public override bool IsNegative {
373                         get {
374                                 return false;
375                         }
376                 }
377         
378                 public override bool IsZeroInteger {
379                         get { return Value == false; }
380                 }
381
382                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
383                 {
384                         return null;
385                 }
386
387         }
388
389         public class ByteConstant : IntegralConstant {
390                 public readonly byte Value;
391
392                 public ByteConstant (byte v, Location loc):
393                         base (loc)
394                 {
395                         Value = v;
396                 }
397
398                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
399                 {
400                         enc.Stream.Write (Value);
401                 }
402
403                 public override void Emit (EmitContext ec)
404                 {
405                         ec.EmitInt (Value);
406                 }
407
408                 public override string AsString ()
409                 {
410                         return Value.ToString ();
411                 }
412
413                 protected override Expression DoResolve (ResolveContext ec)
414                 {
415                         type = TypeManager.byte_type;
416                         eclass = ExprClass.Value;
417                         return this;
418                 }
419
420                 public override object GetValue ()
421                 {
422                         return Value;
423                 }
424
425                 public override Constant Increment ()
426                 {
427                         return new ByteConstant (checked ((byte)(Value + 1)), loc);
428                 }
429
430                 public override bool IsDefaultValue {
431                         get {
432                                 return Value == 0;
433                         }
434                 }
435
436                 public override bool IsOneInteger {
437                         get {
438                                 return Value == 1;
439                         }
440                 }               
441
442                 public override bool IsNegative {
443                         get {
444                                 return false;
445                         }
446                 }
447
448                 public override bool IsZeroInteger {
449                         get { return Value == 0; }
450                 }
451
452                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
453                 {
454                         if (target_type == TypeManager.sbyte_type) {
455                                 if (in_checked_context){
456                                         if (Value > SByte.MaxValue)
457                                                 throw new OverflowException ();
458                                 }
459                                 return new SByteConstant ((sbyte) Value, Location);
460                         }
461                         if (target_type == TypeManager.short_type)
462                                 return new ShortConstant ((short) Value, Location);
463                         if (target_type == TypeManager.ushort_type)
464                                 return new UShortConstant ((ushort) Value, Location);
465                         if (target_type == TypeManager.int32_type)
466                                 return new IntConstant ((int) Value, Location);
467                         if (target_type == TypeManager.uint32_type)
468                                 return new UIntConstant ((uint) Value, Location);
469                         if (target_type == TypeManager.int64_type)
470                                 return new LongConstant ((long) Value, Location);
471                         if (target_type == TypeManager.uint64_type)
472                                 return new ULongConstant ((ulong) Value, Location);
473                         if (target_type == TypeManager.float_type)
474                                 return new FloatConstant ((float) Value, Location);
475                         if (target_type == TypeManager.double_type)
476                                 return new DoubleConstant ((double) Value, Location);
477                         if (target_type == TypeManager.char_type)
478                                 return new CharConstant ((char) Value, Location);
479                         if (target_type == TypeManager.decimal_type)
480                                 return new DecimalConstant ((decimal) Value, Location);
481
482                         return null;
483                 }
484
485         }
486
487         public class CharConstant : Constant {
488                 public readonly char Value;
489
490                 public CharConstant (char v, Location loc):
491                         base (loc)
492                 {
493                         Value = v;
494                 }
495
496                 protected override Expression DoResolve (ResolveContext rc)
497                 {
498                         type = TypeManager.char_type;
499                         eclass = ExprClass.Value;
500                         return this;
501                 }
502
503                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
504                 {
505                         enc.Stream.Write ((ushort) Value);
506                 }
507
508                 public override void Emit (EmitContext ec)
509                 {
510                         ec.EmitInt (Value);
511                 }
512
513                 static string descape (char c)
514                 {
515                         switch (c){
516                         case '\a':
517                                 return "\\a"; 
518                         case '\b':
519                                 return "\\b"; 
520                         case '\n':
521                                 return "\\n"; 
522                         case '\t':
523                                 return "\\t"; 
524                         case '\v':
525                                 return "\\v"; 
526                         case '\r':
527                                 return "\\r"; 
528                         case '\\':
529                                 return "\\\\";
530                         case '\f':
531                                 return "\\f"; 
532                         case '\0':
533                                 return "\\0"; 
534                         case '"':
535                                 return "\\\""; 
536                         case '\'':
537                                 return "\\\'"; 
538                         }
539                         return c.ToString ();
540                 }
541
542                 public override string AsString ()
543                 {
544                         return "\"" + descape (Value) + "\"";
545                 }
546
547                 public override object GetValue ()
548                 {
549                         return Value;
550                 }
551
552                 public override bool IsDefaultValue {
553                         get {
554                                 return Value == 0;
555                         }
556                 }
557
558                 public override bool IsNegative {
559                         get {
560                                 return false;
561                         }
562                 }
563
564                 public override bool IsZeroInteger {
565                         get { return Value == '\0'; }
566                 }
567
568                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
569                 {
570                         if (target_type == TypeManager.byte_type) {
571                                 if (in_checked_context){
572                                         if (Value < Byte.MinValue || Value > Byte.MaxValue)
573                                                 throw new OverflowException ();
574                                 }
575                                 return new ByteConstant ((byte) Value, Location);
576                         }
577                         if (target_type == TypeManager.sbyte_type) {
578                                 if (in_checked_context){
579                                         if (Value > SByte.MaxValue)
580                                                 throw new OverflowException ();
581                                 }
582                                 return new SByteConstant ((sbyte) Value, Location);
583                         }
584                         if (target_type == TypeManager.short_type) {
585                                 if (in_checked_context){
586                                         if (Value > Int16.MaxValue)
587                                                 throw new OverflowException ();
588                                 }                                       
589                                 return new ShortConstant ((short) Value, Location);
590                         }
591                         if (target_type == TypeManager.int32_type)
592                                 return new IntConstant ((int) Value, Location);
593                         if (target_type == TypeManager.uint32_type)
594                                 return new UIntConstant ((uint) Value, Location);
595                         if (target_type == TypeManager.int64_type)
596                                 return new LongConstant ((long) Value, Location);
597                         if (target_type == TypeManager.uint64_type)
598                                 return new ULongConstant ((ulong) Value, Location);
599                         if (target_type == TypeManager.float_type)
600                                 return new FloatConstant ((float) Value, Location);
601                         if (target_type == TypeManager.double_type)
602                                 return new DoubleConstant ((double) Value, Location);
603                         if (target_type == TypeManager.decimal_type)
604                                 return new DecimalConstant ((decimal) Value, Location);
605
606                         return null;
607                 }
608
609         }
610
611         public class SByteConstant : IntegralConstant {
612                 public readonly sbyte Value;
613
614                 public SByteConstant (sbyte v, Location loc):
615                         base (loc)
616                 {
617                         Value = v;
618                 }
619
620                 protected override Expression DoResolve (ResolveContext rc)
621                 {
622                         type = TypeManager.sbyte_type;
623                         eclass = ExprClass.Value;
624                         return this;
625                 }
626
627                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
628                 {
629                         enc.Stream.Write (Value);
630                 }
631
632                 public override void Emit (EmitContext ec)
633                 {
634                         ec.EmitInt (Value);
635                 }
636
637                 public override string AsString ()
638                 {
639                         return Value.ToString ();
640                 }
641
642                 public override object GetValue ()
643                 {
644                         return Value;
645                 }
646
647                 public override Constant Increment ()
648                 {
649                     return new SByteConstant (checked((sbyte)(Value + 1)), loc);
650                 }
651
652                 public override bool IsDefaultValue {
653                         get {
654                                 return Value == 0;
655                         }
656                 }
657
658                 public override bool IsNegative {
659                         get {
660                                 return Value < 0;
661                         }
662                 }
663                 
664                 public override bool IsOneInteger {
665                         get {
666                                 return Value == 1;
667                         }
668                 }               
669                 
670                 public override bool IsZeroInteger {
671                         get { return Value == 0; }
672                 }
673
674                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
675                 {
676                         if (target_type == TypeManager.byte_type) {
677                                 if (in_checked_context && Value < 0)
678                                         throw new OverflowException ();
679                                 return new ByteConstant ((byte) Value, Location);
680                         }
681                         if (target_type == TypeManager.short_type)
682                                 return new ShortConstant ((short) Value, Location);
683                         if (target_type == TypeManager.ushort_type) {
684                                 if (in_checked_context && Value < 0)
685                                         throw new OverflowException ();
686                                 return new UShortConstant ((ushort) Value, Location);
687                         } if (target_type == TypeManager.int32_type)
688                                   return new IntConstant ((int) Value, Location);
689                         if (target_type == TypeManager.uint32_type) {
690                                 if (in_checked_context && Value < 0)
691                                         throw new OverflowException ();
692                                 return new UIntConstant ((uint) Value, Location);
693                         } if (target_type == TypeManager.int64_type)
694                                   return new LongConstant ((long) Value, Location);
695                         if (target_type == TypeManager.uint64_type) {
696                                 if (in_checked_context && Value < 0)
697                                         throw new OverflowException ();
698                                 return new ULongConstant ((ulong) Value, Location);
699                         }
700                         if (target_type == TypeManager.float_type)
701                                 return new FloatConstant ((float) Value, Location);
702                         if (target_type == TypeManager.double_type)
703                                 return new DoubleConstant ((double) Value, Location);
704                         if (target_type == TypeManager.char_type) {
705                                 if (in_checked_context && Value < 0)
706                                         throw new OverflowException ();
707                                 return new CharConstant ((char) Value, Location);
708                         }
709                         if (target_type == TypeManager.decimal_type)
710                                 return new DecimalConstant ((decimal) Value, Location);
711
712                         return null;
713                 }
714
715         }
716
717         public class ShortConstant : IntegralConstant {
718                 public readonly short Value;
719
720                 public ShortConstant (short v, Location loc):
721                         base (loc)
722                 {
723                         Value = v;
724                 }
725
726                 protected override Expression DoResolve (ResolveContext rc)
727                 {
728                         type = TypeManager.short_type;
729                         eclass = ExprClass.Value;
730                         return this;
731                 }
732
733                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
734                 {
735                         enc.Stream.Write (Value);
736                 }
737
738                 public override void Emit (EmitContext ec)
739                 {
740                         ec.EmitInt (Value);
741                 }
742
743                 public override string AsString ()
744                 {
745                         return Value.ToString ();
746                 }
747
748                 public override object GetValue ()
749                 {
750                         return Value;
751                 }
752
753                 public override Constant Increment ()
754                 {
755                         return new ShortConstant (checked((short)(Value + 1)), loc);
756                 }
757
758                 public override bool IsDefaultValue {
759                         get {
760                                 return Value == 0;
761                         }
762                 }
763                 
764                 public override bool IsZeroInteger {
765                         get { return Value == 0; }
766                 }
767
768                 public override bool IsNegative {
769                         get {
770                                 return Value < 0;
771                         }
772                 }
773                 
774                 public override bool IsOneInteger {
775                         get {
776                                 return Value == 1;
777                         }
778                 }               
779
780                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
781                 {
782                         if (target_type == TypeManager.byte_type) {
783                                 if (in_checked_context){
784                                         if (Value < Byte.MinValue || Value > Byte.MaxValue)
785                                                 throw new OverflowException ();
786                                 }
787                                 return new ByteConstant ((byte) Value, Location);
788                         }
789                         if (target_type == TypeManager.sbyte_type) {
790                                 if (in_checked_context){
791                                         if (Value < SByte.MinValue || Value > SByte.MaxValue)
792                                                 throw new OverflowException ();
793                                 }
794                                 return new SByteConstant ((sbyte) Value, Location);
795                         }
796                         if (target_type == TypeManager.ushort_type) {
797                                 if (in_checked_context && Value < 0)
798                                         throw new OverflowException ();
799                                 
800                                 return new UShortConstant ((ushort) Value, Location);
801                         }
802                         if (target_type == TypeManager.int32_type)
803                                 return new IntConstant ((int) Value, Location);
804                         if (target_type == TypeManager.uint32_type) {
805                                 if (in_checked_context && Value < 0)
806                                         throw new OverflowException ();
807                                 return new UIntConstant ((uint) Value, Location);
808                         }
809                         if (target_type == TypeManager.int64_type)
810                                 return new LongConstant ((long) Value, Location);
811                         if (target_type == TypeManager.uint64_type) {
812                                 if (in_checked_context && Value < 0)
813                                         throw new OverflowException ();
814                                 return new ULongConstant ((ulong) Value, Location);
815                         }
816                         if (target_type == TypeManager.float_type)
817                                 return new FloatConstant ((float) Value, Location);
818                         if (target_type == TypeManager.double_type)
819                                 return new DoubleConstant ((double) Value, Location);
820                         if (target_type == TypeManager.char_type) {
821                                 if (in_checked_context){
822                                         if (Value < Char.MinValue)
823                                                 throw new OverflowException ();
824                                 }
825                                 return new CharConstant ((char) Value, Location);
826                         }
827                         if (target_type == TypeManager.decimal_type)
828                                 return new DecimalConstant ((decimal) Value, Location);
829
830                         return null;
831                 }
832
833         }
834
835         public class UShortConstant : IntegralConstant {
836                 public readonly ushort Value;
837
838                 public UShortConstant (ushort v, Location loc):
839                         base (loc)
840                 {
841                         Value = v;
842                 }
843
844                 protected override Expression DoResolve (ResolveContext rc)
845                 {
846                         type = TypeManager.ushort_type;
847                         eclass = ExprClass.Value;
848                         return this;
849                 }
850
851                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
852                 {
853                         enc.Stream.Write (Value);
854                 }
855
856                 public override void Emit (EmitContext ec)
857                 {
858                         ec.EmitInt (Value);
859                 }
860
861                 public override string AsString ()
862                 {
863                         return Value.ToString ();
864                 }
865
866                 public override object GetValue ()
867                 {
868                         return Value;
869                 }
870         
871                 public override Constant Increment ()
872                 {
873                         return new UShortConstant (checked((ushort)(Value + 1)), loc);
874                 }
875
876                 public override bool IsDefaultValue {
877                         get {
878                                 return Value == 0;
879                         }
880                 }
881
882                 public override bool IsNegative {
883                         get {
884                                 return false;
885                         }
886                 }
887                 
888                 public override bool IsOneInteger {
889                         get {
890                                 return Value == 1;
891                         }
892                 }               
893         
894                 public override bool IsZeroInteger {
895                         get { return Value == 0; }
896                 }
897
898                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
899                 {
900                         if (target_type == TypeManager.byte_type) {
901                                 if (in_checked_context){
902                                         if (Value > Byte.MaxValue)
903                                                 throw new OverflowException ();
904                                 }
905                                 return new ByteConstant ((byte) Value, Location);
906                         }
907                         if (target_type == TypeManager.sbyte_type) {
908                                 if (in_checked_context){
909                                         if (Value > SByte.MaxValue)
910                                                 throw new OverflowException ();
911                                 }
912                                 return new SByteConstant ((sbyte) Value, Location);
913                         }
914                         if (target_type == TypeManager.short_type) {
915                                 if (in_checked_context){
916                                         if (Value > Int16.MaxValue)
917                                                 throw new OverflowException ();
918                                 }
919                                 return new ShortConstant ((short) Value, Location);
920                         }
921                         if (target_type == TypeManager.int32_type)
922                                 return new IntConstant ((int) Value, Location);
923                         if (target_type == TypeManager.uint32_type)
924                                 return new UIntConstant ((uint) Value, Location);
925                         if (target_type == TypeManager.int64_type)
926                                 return new LongConstant ((long) Value, Location);
927                         if (target_type == TypeManager.uint64_type)
928                                 return new ULongConstant ((ulong) Value, Location);
929                         if (target_type == TypeManager.float_type)
930                                 return new FloatConstant ((float) Value, Location);
931                         if (target_type == TypeManager.double_type)
932                                 return new DoubleConstant ((double) Value, Location);
933                         if (target_type == TypeManager.char_type) {
934                                 if (in_checked_context){
935                                         if (Value > Char.MaxValue)
936                                                 throw new OverflowException ();
937                                 }
938                                 return new CharConstant ((char) Value, Location);
939                         }
940                         if (target_type == TypeManager.decimal_type)
941                                 return new DecimalConstant ((decimal) Value, Location);
942
943                         return null;
944                 }
945         }
946
947         public class IntConstant : IntegralConstant {
948                 public readonly int Value;
949
950                 public IntConstant (int v, Location loc):
951                         base (loc)
952                 {
953                         Value = v;
954                 }
955
956                 protected override Expression DoResolve (ResolveContext rc)
957                 {
958                         type = TypeManager.int32_type;
959                         eclass = ExprClass.Value;
960                         return this;
961                 }
962
963                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
964                 {
965                         enc.Stream.Write (Value);
966                 }
967
968                 public override void Emit (EmitContext ec)
969                 {
970                         ec.EmitInt (Value);
971                 }
972
973                 public override string AsString ()
974                 {
975                         return Value.ToString ();
976                 }
977
978                 public override object GetValue ()
979                 {
980                         return Value;
981                 }
982
983                 public override Constant Increment ()
984                 {
985                         return new IntConstant (checked(Value + 1), loc);
986                 }
987
988                 public override bool IsDefaultValue {
989                         get {
990                                 return Value == 0;
991                         }
992                 }
993                 
994                 public override bool IsNegative {
995                         get {
996                                 return Value < 0;
997                         }
998                 }
999                 
1000                 public override bool IsOneInteger {
1001                         get {
1002                                 return Value == 1;
1003                         }
1004                 }               
1005
1006                 public override bool IsZeroInteger {
1007                         get { return Value == 0; }
1008                 }
1009
1010                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1011                 {
1012                         if (target_type == TypeManager.byte_type) {
1013                                 if (in_checked_context){
1014                                         if (Value < Byte.MinValue || Value > Byte.MaxValue)
1015                                                 throw new OverflowException ();
1016                                 }
1017                                 return new ByteConstant ((byte) Value, Location);
1018                         }
1019                         if (target_type == TypeManager.sbyte_type) {
1020                                 if (in_checked_context){
1021                                         if (Value < SByte.MinValue || Value > SByte.MaxValue)
1022                                                 throw new OverflowException ();
1023                                 }
1024                                 return new SByteConstant ((sbyte) Value, Location);
1025                         }
1026                         if (target_type == TypeManager.short_type) {
1027                                 if (in_checked_context){
1028                                         if (Value < Int16.MinValue || Value > Int16.MaxValue)
1029                                                 throw new OverflowException ();
1030                                 }
1031                                 return new ShortConstant ((short) Value, Location);
1032                         }
1033                         if (target_type == TypeManager.ushort_type) {
1034                                 if (in_checked_context){
1035                                         if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1036                                                 throw new OverflowException ();
1037                                 }
1038                                 return new UShortConstant ((ushort) Value, Location);
1039                         }
1040                         if (target_type == TypeManager.uint32_type) {
1041                                 if (in_checked_context){
1042                                         if (Value < UInt32.MinValue)
1043                                                 throw new OverflowException ();
1044                                 }
1045                                 return new UIntConstant ((uint) Value, Location);
1046                         }
1047                         if (target_type == TypeManager.int64_type)
1048                                 return new LongConstant ((long) Value, Location);
1049                         if (target_type == TypeManager.uint64_type) {
1050                                 if (in_checked_context && Value < 0)
1051                                         throw new OverflowException ();
1052                                 return new ULongConstant ((ulong) Value, Location);
1053                         }
1054                         if (target_type == TypeManager.float_type)
1055                                 return new FloatConstant ((float) Value, Location);
1056                         if (target_type == TypeManager.double_type)
1057                                 return new DoubleConstant ((double) Value, Location);
1058                         if (target_type == TypeManager.char_type) {
1059                                 if (in_checked_context){
1060                                         if (Value < Char.MinValue || Value > Char.MaxValue)
1061                                                 throw new OverflowException ();
1062                                 }
1063                                 return new CharConstant ((char) Value, Location);
1064                         }
1065                         if (target_type == TypeManager.decimal_type)
1066                                 return new DecimalConstant ((decimal) Value, Location);
1067
1068                         return null;
1069                 }
1070
1071                 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1072                 {
1073                         if (this.type == type)
1074                                 return this;
1075
1076                         Constant c = TryImplicitIntConversion (type);
1077                         if (c != null)
1078                                 return c.Resolve (rc);
1079
1080                         return base.ConvertImplicitly (rc, type);
1081                 }
1082
1083                 /// <summary>
1084                 ///   Attempts to perform an implicit constant conversion of the IntConstant
1085                 ///   into a different data type using casts (See Implicit Constant
1086                 ///   Expression Conversions)
1087                 /// </summary>
1088                 Constant TryImplicitIntConversion (TypeSpec target_type)
1089                 {
1090                         if (target_type == TypeManager.sbyte_type) {
1091                                 if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1092                                         return new SByteConstant ((sbyte) Value, loc);
1093                         } 
1094                         else if (target_type == TypeManager.byte_type) {
1095                                 if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1096                                         return new ByteConstant ((byte) Value, loc);
1097                         } 
1098                         else if (target_type == TypeManager.short_type) {
1099                                 if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1100                                         return new ShortConstant ((short) Value, loc);
1101                         } 
1102                         else if (target_type == TypeManager.ushort_type) {
1103                                 if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1104                                         return new UShortConstant ((ushort) Value, loc);
1105                         } 
1106                         else if (target_type == TypeManager.uint32_type) {
1107                                 if (Value >= 0)
1108                                         return new UIntConstant ((uint) Value, loc);
1109                         } 
1110                         else if (target_type == TypeManager.uint64_type) {
1111                                 //
1112                                 // we can optimize this case: a positive int32
1113                                 // always fits on a uint64.  But we need an opcode
1114                                 // to do it.
1115                                 //
1116                                 if (Value >= 0)
1117                                         return new ULongConstant ((ulong) Value, loc);
1118                         } 
1119                         else if (target_type == TypeManager.double_type)
1120                                 return new DoubleConstant ((double) Value, loc);
1121                         else if (target_type == TypeManager.float_type)
1122                                 return new FloatConstant ((float) Value, loc);
1123
1124                         return null;
1125                 }
1126         }
1127
1128         public class UIntConstant : IntegralConstant {
1129                 public readonly uint Value;
1130
1131                 public UIntConstant (uint v, Location loc):
1132                         base (loc)
1133                 {
1134                         Value = v;
1135                 }
1136
1137                 protected override Expression DoResolve (ResolveContext rc)
1138                 {
1139                         type = TypeManager.uint32_type;
1140                         eclass = ExprClass.Value;
1141                         return this;
1142                 }
1143
1144                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1145                 {
1146                         enc.Stream.Write (Value);
1147                 }
1148
1149                 public override void Emit (EmitContext ec)
1150                 {
1151                         ec.EmitInt (unchecked ((int) Value));
1152                 }
1153
1154                 public override string AsString ()
1155                 {
1156                         return Value.ToString ();
1157                 }
1158
1159                 public override object GetValue ()
1160                 {
1161                         return Value;
1162                 }
1163
1164                 public override Constant Increment ()
1165                 {
1166                         return new UIntConstant (checked(Value + 1), loc);
1167                 }
1168         
1169                 public override bool IsDefaultValue {
1170                         get {
1171                                 return Value == 0;
1172                         }
1173                 }
1174
1175                 public override bool IsNegative {
1176                         get {
1177                                 return false;
1178                         }
1179                 }
1180                 
1181                 public override bool IsOneInteger {
1182                         get {
1183                                 return Value == 1;
1184                         }
1185                 }               
1186
1187                 public override bool IsZeroInteger {
1188                         get { return Value == 0; }
1189                 }
1190
1191                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1192                 {
1193                         if (target_type == TypeManager.byte_type) {
1194                                 if (in_checked_context){
1195                                         if (Value < Char.MinValue || Value > Char.MaxValue)
1196                                                 throw new OverflowException ();
1197                                 }
1198                                 return new ByteConstant ((byte) Value, Location);
1199                         }
1200                         if (target_type == TypeManager.sbyte_type) {
1201                                 if (in_checked_context){
1202                                         if (Value > SByte.MaxValue)
1203                                                 throw new OverflowException ();
1204                                 }
1205                                 return new SByteConstant ((sbyte) Value, Location);
1206                         }
1207                         if (target_type == TypeManager.short_type) {
1208                                 if (in_checked_context){
1209                                         if (Value > Int16.MaxValue)
1210                                                 throw new OverflowException ();
1211                                 }
1212                                 return new ShortConstant ((short) Value, Location);
1213                         }
1214                         if (target_type == TypeManager.ushort_type) {
1215                                 if (in_checked_context){
1216                                         if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1217                                                 throw new OverflowException ();
1218                                 }
1219                                 return new UShortConstant ((ushort) Value, Location);
1220                         }
1221                         if (target_type == TypeManager.int32_type) {
1222                                 if (in_checked_context){
1223                                         if (Value > Int32.MaxValue)
1224                                                 throw new OverflowException ();
1225                                 }
1226                                 return new IntConstant ((int) Value, Location);
1227                         }
1228                         if (target_type == TypeManager.int64_type)
1229                                 return new LongConstant ((long) Value, Location);
1230                         if (target_type == TypeManager.uint64_type)
1231                                 return new ULongConstant ((ulong) Value, Location);
1232                         if (target_type == TypeManager.float_type)
1233                                 return new FloatConstant ((float) Value, Location);
1234                         if (target_type == TypeManager.double_type)
1235                                 return new DoubleConstant ((double) Value, Location);
1236                         if (target_type == TypeManager.char_type) {
1237                                 if (in_checked_context){
1238                                         if (Value < Char.MinValue || Value > Char.MaxValue)
1239                                                 throw new OverflowException ();
1240                                 }
1241                                 return new CharConstant ((char) Value, Location);
1242                         }
1243                         if (target_type == TypeManager.decimal_type)
1244                                 return new DecimalConstant ((decimal) Value, Location);
1245
1246                         return null;
1247                 }
1248
1249         }
1250
1251         public class LongConstant : IntegralConstant {
1252                 public readonly long Value;
1253
1254                 public LongConstant (long v, Location loc):
1255                         base (loc)
1256                 {
1257                         Value = v;
1258                 }
1259
1260                 protected override Expression DoResolve (ResolveContext rc)
1261                 {
1262                         type = TypeManager.int64_type;
1263                         eclass = ExprClass.Value;
1264                         return this;
1265                 }
1266
1267                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1268                 {
1269                         enc.Stream.Write (Value);
1270                 }
1271
1272                 public override void Emit (EmitContext ec)
1273                 {
1274                         ec.EmitLong (Value);
1275                 }
1276
1277                 public override string AsString ()
1278                 {
1279                         return Value.ToString ();
1280                 }
1281
1282                 public override object GetValue ()
1283                 {
1284                         return Value;
1285                 }
1286
1287                 public override Constant Increment ()
1288                 {
1289                         return new LongConstant (checked(Value + 1), loc);
1290                 }
1291                 
1292                 public override bool IsDefaultValue {
1293                         get {
1294                                 return Value == 0;
1295                         }
1296                 }
1297
1298                 public override bool IsNegative {
1299                         get {
1300                                 return Value < 0;
1301                         }
1302                 }
1303                 
1304                 public override bool IsOneInteger {
1305                         get {
1306                                 return Value == 1;
1307                         }
1308                 }               
1309
1310                 public override bool IsZeroInteger {
1311                         get { return Value == 0; }
1312                 }
1313
1314                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1315                 {
1316                         if (target_type == TypeManager.byte_type) {
1317                                 if (in_checked_context){
1318                                         if (Value < Byte.MinValue || Value > Byte.MaxValue)
1319                                                 throw new OverflowException ();
1320                                 }
1321                                 return new ByteConstant ((byte) Value, Location);
1322                         }
1323                         if (target_type == TypeManager.sbyte_type) {
1324                                 if (in_checked_context){
1325                                         if (Value < SByte.MinValue || Value > SByte.MaxValue)
1326                                                 throw new OverflowException ();
1327                                 }
1328                                 return new SByteConstant ((sbyte) Value, Location);
1329                         }
1330                         if (target_type == TypeManager.short_type) {
1331                                 if (in_checked_context){
1332                                         if (Value < Int16.MinValue || Value > Int16.MaxValue)
1333                                                 throw new OverflowException ();
1334                                 }
1335                                 return new ShortConstant ((short) Value, Location);
1336                         }
1337                         if (target_type == TypeManager.ushort_type) {
1338                                 if (in_checked_context){
1339                                         if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1340                                                 throw new OverflowException ();
1341                                 }
1342                                 return new UShortConstant ((ushort) Value, Location);
1343                         }
1344                         if (target_type == TypeManager.int32_type) {
1345                                 if (in_checked_context){
1346                                         if (Value < Int32.MinValue || Value > Int32.MaxValue)
1347                                                 throw new OverflowException ();
1348                                 }
1349                                 return new IntConstant ((int) Value, Location);
1350                         }
1351                         if (target_type == TypeManager.uint32_type) {
1352                                 if (in_checked_context){
1353                                         if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1354                                                 throw new OverflowException ();
1355                                 }
1356                                 return new UIntConstant ((uint) Value, Location);
1357                         }
1358                         if (target_type == TypeManager.uint64_type) {
1359                                 if (in_checked_context && Value < 0)
1360                                         throw new OverflowException ();
1361                                 return new ULongConstant ((ulong) Value, Location);
1362                         }
1363                         if (target_type == TypeManager.float_type)
1364                                 return new FloatConstant ((float) Value, Location);
1365                         if (target_type == TypeManager.double_type)
1366                                 return new DoubleConstant ((double) Value, Location);
1367                         if (target_type == TypeManager.char_type) {
1368                                 if (in_checked_context){
1369                                         if (Value < Char.MinValue || Value > Char.MaxValue)
1370                                                 throw new OverflowException ();
1371                                 }
1372                                 return new CharConstant ((char) Value, Location);
1373                         }
1374                         if (target_type == TypeManager.decimal_type)
1375                                 return new DecimalConstant ((decimal) Value, Location);
1376
1377                         return null;
1378                 }
1379
1380                 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1381                 {
1382                         if (Value >= 0 && type == TypeManager.uint64_type) {
1383                                 return new ULongConstant ((ulong) Value, loc).Resolve (rc);
1384                         }
1385
1386                         return base.ConvertImplicitly (rc, type);
1387                 }
1388         }
1389
1390         public class ULongConstant : IntegralConstant {
1391                 public readonly ulong Value;
1392
1393                 public ULongConstant (ulong v, Location loc):
1394                         base (loc)
1395                 {
1396                         Value = v;
1397                 }
1398
1399                 protected override Expression DoResolve (ResolveContext rc)
1400                 {
1401                         type = TypeManager.uint64_type;
1402                         eclass = ExprClass.Value;
1403                         return this;
1404                 }
1405
1406                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1407                 {
1408                         enc.Stream.Write (Value);
1409                 }
1410
1411                 public override void Emit (EmitContext ec)
1412                 {
1413                         ec.EmitLong (unchecked ((long) Value));
1414                 }
1415
1416                 public override string AsString ()
1417                 {
1418                         return Value.ToString ();
1419                 }
1420
1421                 public override object GetValue ()
1422                 {
1423                         return Value;
1424                 }
1425
1426                 public override Constant Increment ()
1427                 {
1428                         return new ULongConstant (checked(Value + 1), loc);
1429                 }
1430
1431                 public override bool IsDefaultValue {
1432                         get {
1433                                 return Value == 0;
1434                         }
1435                 }
1436
1437                 public override bool IsNegative {
1438                         get {
1439                                 return false;
1440                         }
1441                 }
1442                 
1443                 public override bool IsOneInteger {
1444                         get {
1445                                 return Value == 1;
1446                         }
1447                 }               
1448
1449                 public override bool IsZeroInteger {
1450                         get { return Value == 0; }
1451                 }
1452
1453                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1454                 {
1455                         if (target_type == TypeManager.byte_type) {
1456                                 if (in_checked_context && Value > Byte.MaxValue)
1457                                         throw new OverflowException ();
1458                                 return new ByteConstant ((byte) Value, Location);
1459                         }
1460                         if (target_type == TypeManager.sbyte_type) {
1461                                 if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1462                                         throw new OverflowException ();
1463                                 return new SByteConstant ((sbyte) Value, Location);
1464                         }
1465                         if (target_type == TypeManager.short_type) {
1466                                 if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1467                                         throw new OverflowException ();
1468                                 return new ShortConstant ((short) Value, Location);
1469                         }
1470                         if (target_type == TypeManager.ushort_type) {
1471                                 if (in_checked_context && Value > UInt16.MaxValue)
1472                                         throw new OverflowException ();
1473                                 return new UShortConstant ((ushort) Value, Location);
1474                         }
1475                         if (target_type == TypeManager.int32_type) {
1476                                 if (in_checked_context && Value > UInt32.MaxValue)
1477                                         throw new OverflowException ();
1478                                 return new IntConstant ((int) Value, Location);
1479                         }
1480                         if (target_type == TypeManager.uint32_type) {
1481                                 if  (in_checked_context && Value > UInt32.MaxValue)
1482                                         throw new OverflowException ();
1483                                 return new UIntConstant ((uint) Value, Location);
1484                         }
1485                         if (target_type == TypeManager.int64_type) {
1486                                 if (in_checked_context && Value > Int64.MaxValue)
1487                                         throw new OverflowException ();
1488                                 return new LongConstant ((long) Value, Location);
1489                         }
1490                         if (target_type == TypeManager.float_type)
1491                                 return new FloatConstant ((float) Value, Location);
1492                         if (target_type == TypeManager.double_type)
1493                                 return new DoubleConstant ((double) Value, Location);
1494                         if (target_type == TypeManager.char_type) {
1495                                 if (in_checked_context && Value > Char.MaxValue)
1496                                         throw new OverflowException ();
1497                                 return new CharConstant ((char) Value, Location);
1498                         }
1499                         if (target_type == TypeManager.decimal_type)
1500                                 return new DecimalConstant ((decimal) Value, Location);
1501
1502                         return null;
1503                 }
1504
1505         }
1506
1507         public class FloatConstant : Constant {
1508                 public float Value;
1509
1510                 public FloatConstant (float v, Location loc):
1511                         base (loc)
1512                 {
1513                         Value = v;
1514                 }
1515
1516                 protected override Expression DoResolve (ResolveContext rc)
1517                 {
1518                         type = TypeManager.float_type;
1519                         eclass = ExprClass.Value;
1520                         return this;
1521                 }
1522
1523                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1524                 {
1525                         enc.Stream.Write (Value);
1526                 }
1527
1528                 public override void Emit (EmitContext ec)
1529                 {
1530                         ec.Emit (OpCodes.Ldc_R4, Value);
1531                 }
1532
1533                 public override string AsString ()
1534                 {
1535                         return Value.ToString ();
1536                 }
1537
1538                 public override object GetValue ()
1539                 {
1540                         return Value;
1541                 }
1542
1543                 public override bool IsDefaultValue {
1544                         get {
1545                                 return Value == 0;
1546                         }
1547                 }
1548
1549                 public override bool IsNegative {
1550                         get {
1551                                 return Value < 0;
1552                         }
1553                 }
1554
1555                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1556                 {
1557                         if (target_type == TypeManager.byte_type) {
1558                                 if (in_checked_context){
1559                                         if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1560                                                 throw new OverflowException ();
1561                                 }
1562                                 return new ByteConstant ((byte) Value, Location);
1563                         }
1564                         if (target_type == TypeManager.sbyte_type) {
1565                                 if (in_checked_context){
1566                                         if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1567                                                 throw new OverflowException ();
1568                                 }
1569                                 return new SByteConstant ((sbyte) Value, Location);
1570                         }
1571                         if (target_type == TypeManager.short_type) {
1572                                 if (in_checked_context){
1573                                         if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1574                                                 throw new OverflowException ();
1575                                 }
1576                                 return new ShortConstant ((short) Value, Location);
1577                         }
1578                         if (target_type == TypeManager.ushort_type) {
1579                                 if (in_checked_context){
1580                                         if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1581                                                 throw new OverflowException ();
1582                                 }
1583                                 return new UShortConstant ((ushort) Value, Location);
1584                         }
1585                         if (target_type == TypeManager.int32_type) {
1586                                 if (in_checked_context){
1587                                         if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1588                                                 throw new OverflowException ();
1589                                 }
1590                                 return new IntConstant ((int) Value, Location);
1591                         }
1592                         if (target_type == TypeManager.uint32_type) {
1593                                 if (in_checked_context){
1594                                         if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1595                                                 throw new OverflowException ();
1596                                 }
1597                                 return new UIntConstant ((uint) Value, Location);
1598                         }
1599                         if (target_type == TypeManager.int64_type) {
1600                                 if (in_checked_context){
1601                                         if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1602                                                 throw new OverflowException ();
1603                                 }
1604                                 return new LongConstant ((long) Value, Location);
1605                         }
1606                         if (target_type == TypeManager.uint64_type) {
1607                                 if (in_checked_context){
1608                                         if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1609                                                 throw new OverflowException ();
1610                                 }
1611                                 return new ULongConstant ((ulong) Value, Location);
1612                         }
1613                         if (target_type == TypeManager.double_type)
1614                                 return new DoubleConstant ((double) Value, Location);
1615                         if (target_type == TypeManager.char_type) {
1616                                 if (in_checked_context){
1617                                         if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1618                                                 throw new OverflowException ();
1619                                 }
1620                                 return new CharConstant ((char) Value, Location);
1621                         }
1622                         if (target_type == TypeManager.decimal_type)
1623                                 return new DecimalConstant ((decimal) Value, Location);
1624
1625                         return null;
1626                 }
1627
1628         }
1629
1630         public class DoubleConstant : Constant {
1631                 public double Value;
1632
1633                 public DoubleConstant (double v, Location loc):
1634                         base (loc)
1635                 {
1636                         Value = v;
1637                 }
1638
1639                 protected override Expression DoResolve (ResolveContext rc)
1640                 {
1641                         type = TypeManager.double_type;
1642                         eclass = ExprClass.Value;
1643                         return this;
1644                 }
1645
1646                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1647                 {
1648                         enc.Stream.Write (Value);
1649                 }
1650
1651                 public override void Emit (EmitContext ec)
1652                 {
1653                         ec.Emit (OpCodes.Ldc_R8, Value);
1654                 }
1655
1656                 public override string AsString ()
1657                 {
1658                         return Value.ToString ();
1659                 }
1660
1661                 public override object GetValue ()
1662                 {
1663                         return Value;
1664                 }
1665
1666                 public override bool IsDefaultValue {
1667                         get {
1668                                 return Value == 0;
1669                         }
1670                 }
1671
1672                 public override bool IsNegative {
1673                         get {
1674                                 return Value < 0;
1675                         }
1676                 }
1677
1678                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1679                 {
1680                         if (target_type == TypeManager.byte_type) {
1681                                 if (in_checked_context){
1682                                         if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1683                                                 throw new OverflowException ();
1684                                 }
1685                                 return new ByteConstant ((byte) Value, Location);
1686                         }
1687                         if (target_type == TypeManager.sbyte_type) {
1688                                 if (in_checked_context){
1689                                         if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1690                                                 throw new OverflowException ();
1691                                 }
1692                                 return new SByteConstant ((sbyte) Value, Location);
1693                         }
1694                         if (target_type == TypeManager.short_type) {
1695                                 if (in_checked_context){
1696                                         if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1697                                                 throw new OverflowException ();
1698                                 }
1699                                 return new ShortConstant ((short) Value, Location);
1700                         }
1701                         if (target_type == TypeManager.ushort_type) {
1702                                 if (in_checked_context){
1703                                         if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1704                                                 throw new OverflowException ();
1705                                 }
1706                                 return new UShortConstant ((ushort) Value, Location);
1707                         }
1708                         if (target_type == TypeManager.int32_type) {
1709                                 if (in_checked_context){
1710                                         if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1711                                                 throw new OverflowException ();
1712                                 }
1713                                 return new IntConstant ((int) Value, Location);
1714                         }
1715                         if (target_type == TypeManager.uint32_type) {
1716                                 if (in_checked_context){
1717                                         if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1718                                                 throw new OverflowException ();
1719                                 }
1720                                 return new UIntConstant ((uint) Value, Location);
1721                         }
1722                         if (target_type == TypeManager.int64_type) {
1723                                 if (in_checked_context){
1724                                         if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1725                                                 throw new OverflowException ();
1726                                 }
1727                                 return new LongConstant ((long) Value, Location);
1728                         }
1729                         if (target_type == TypeManager.uint64_type) {
1730                                 if (in_checked_context){
1731                                         if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1732                                                 throw new OverflowException ();
1733                                 }
1734                                 return new ULongConstant ((ulong) Value, Location);
1735                         }
1736                         if (target_type == TypeManager.float_type)
1737                                 return new FloatConstant ((float) Value, Location);
1738                         if (target_type == TypeManager.char_type) {
1739                                 if (in_checked_context){
1740                                         if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1741                                                 throw new OverflowException ();
1742                                 }
1743                                 return new CharConstant ((char) Value, Location);
1744                         }
1745                         if (target_type == TypeManager.decimal_type)
1746                                 return new DecimalConstant ((decimal) Value, Location);
1747
1748                         return null;
1749                 }
1750
1751         }
1752
1753         public class DecimalConstant : Constant {
1754                 public readonly decimal Value;
1755
1756                 public DecimalConstant (decimal d, Location loc):
1757                         base (loc)
1758                 {
1759                         Value = d;
1760                 }
1761
1762                 override public string AsString ()
1763                 {
1764                         return Value.ToString () + "M";
1765                 }
1766
1767                 protected override Expression DoResolve (ResolveContext rc)
1768                 {
1769                         type = TypeManager.decimal_type;
1770                         eclass = ExprClass.Value;
1771                         return this;
1772                 }
1773
1774                 public override object GetValue ()
1775                 {
1776                         return (object) Value;
1777                 }
1778
1779                 public override void Emit (EmitContext ec)
1780                 {
1781                         int [] words = decimal.GetBits (Value);
1782                         int power = (words [3] >> 16) & 0xff;
1783
1784                         if (power == 0) {
1785                                 if (Value <= int.MaxValue && Value >= int.MinValue) {
1786                                         if (TypeManager.void_decimal_ctor_int_arg == null) {
1787                                                 TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor (
1788                                                         TypeManager.decimal_type, loc, TypeManager.int32_type);
1789
1790                                                 if (TypeManager.void_decimal_ctor_int_arg == null)
1791                                                         return;
1792                                         }
1793
1794                                         ec.EmitInt ((int) Value);
1795                                         ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1796                                         return;
1797                                 }
1798
1799                                 if (Value <= long.MaxValue && Value >= long.MinValue) {
1800                                         if (TypeManager.void_decimal_ctor_long_arg == null) {
1801                                                 TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor (
1802                                                         TypeManager.decimal_type, loc, TypeManager.int64_type);
1803
1804                                                 if (TypeManager.void_decimal_ctor_long_arg == null)
1805                                                         return;
1806                                         }
1807
1808                                         ec.EmitLong ((long) Value);
1809                                         ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg);
1810                                         return;
1811                                 }
1812                         }
1813
1814                         ec.EmitInt (words [0]);
1815                         ec.EmitInt (words [1]);
1816                         ec.EmitInt (words [2]);
1817
1818                         // sign
1819                         ec.EmitInt (words [3] >> 31);
1820
1821                         // power
1822                         ec.EmitInt (power);
1823
1824                         if (TypeManager.void_decimal_ctor_five_args == null) {
1825                                 TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor (
1826                                         TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type,
1827                                         TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type);
1828
1829                                 if (TypeManager.void_decimal_ctor_five_args == null)
1830                                         return;
1831                         }
1832
1833                         ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1834                 }
1835
1836                 public override bool IsDefaultValue {
1837                         get {
1838                                 return Value == 0;
1839                         }
1840                 }
1841
1842                 public override bool IsNegative {
1843                         get {
1844                                 return Value < 0;
1845                         }
1846                 }
1847
1848                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1849                 {
1850                         if (target_type == TypeManager.sbyte_type)
1851                                 return new SByteConstant ((sbyte)Value, loc);
1852                         if (target_type == TypeManager.byte_type)
1853                                 return new ByteConstant ((byte)Value, loc);
1854                         if (target_type == TypeManager.short_type)
1855                                 return new ShortConstant ((short)Value, loc);
1856                         if (target_type == TypeManager.ushort_type)
1857                                 return new UShortConstant ((ushort)Value, loc);
1858                         if (target_type == TypeManager.int32_type)
1859                                 return new IntConstant ((int)Value, loc);
1860                         if (target_type == TypeManager.uint32_type)
1861                                 return new UIntConstant ((uint)Value, loc);
1862                         if (target_type == TypeManager.int64_type)
1863                                 return new LongConstant ((long)Value, loc);
1864                         if (target_type == TypeManager.uint64_type)
1865                                 return new ULongConstant ((ulong)Value, loc);
1866                         if (target_type == TypeManager.char_type)
1867                                 return new CharConstant ((char)Value, loc);
1868                         if (target_type == TypeManager.float_type)
1869                                 return new FloatConstant ((float)Value, loc);
1870                         if (target_type == TypeManager.double_type)
1871                                 return new DoubleConstant ((double)Value, loc);
1872
1873                         return null;
1874                 }
1875
1876         }
1877
1878         public class StringConstant : Constant {
1879                 public readonly string Value;
1880
1881                 public StringConstant (string s, Location loc):
1882                         base (loc)
1883                 {
1884                         Value = s;
1885                 }
1886
1887                 // FIXME: Escape the string.
1888                 override public string AsString ()
1889                 {
1890                         return "\"" + Value + "\"";
1891                 }
1892
1893                 protected override Expression DoResolve (ResolveContext rc)
1894                 {
1895                         type = TypeManager.string_type;
1896                         eclass = ExprClass.Value;
1897                         return this;
1898                 }
1899
1900                 public override object GetValue ()
1901                 {
1902                         return Value;
1903                 }
1904                 
1905                 public override void Emit (EmitContext ec)
1906                 {
1907                         if (Value == null) {
1908                                 ec.Emit (OpCodes.Ldnull);
1909                                 return;
1910                         }
1911
1912                         //
1913                         // Use string.Empty for both literals and constants even if
1914                         // it's not allowed at language level
1915                         //
1916                         if (Value.Length == 0 && RootContext.Optimize && ec.CurrentType != TypeManager.string_type) {
1917                                 if (TypeManager.string_empty == null)
1918                                         TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type);
1919
1920                                 if (TypeManager.string_empty != null) {
1921                                         ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty);
1922                                         return;
1923                                 }
1924                         }
1925
1926                         ec.Emit (OpCodes.Ldstr, Value);
1927                 }
1928
1929                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1930                 {
1931                         // cast to object
1932                         if (type != targetType)
1933                                 enc.Encode (type);
1934
1935                         enc.Encode (Value);
1936                 }
1937
1938                 public override bool IsDefaultValue {
1939                         get {
1940                                 return Value == null;
1941                         }
1942                 }
1943
1944                 public override bool IsNegative {
1945                         get {
1946                                 return false;
1947                         }
1948                 }
1949
1950                 public override bool IsNull {
1951                         get {
1952                                 return IsDefaultValue;
1953                         }
1954                 }
1955
1956                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1957                 {
1958                         return null;
1959                 }
1960         }
1961
1962         //
1963         // Null constant can have its own type, think of `default (Foo)'
1964         //
1965         public class NullConstant : Constant
1966         {
1967                 public NullConstant (TypeSpec type, Location loc)
1968                         : base (loc)
1969                 {
1970                         eclass = ExprClass.Value;
1971                         this.type = type;
1972                 }
1973
1974                 public override string AsString ()
1975                 {
1976                         return GetSignatureForError ();
1977                 }
1978
1979                 public override Expression CreateExpressionTree (ResolveContext ec)
1980                 {
1981                         if (type == InternalType.Null || type == TypeManager.object_type) {
1982                                 // Optimized version, also avoids referencing literal internal type
1983                                 Arguments args = new Arguments (1);
1984                                 args.Add (new Argument (this));
1985                                 return CreateExpressionFactoryCall (ec, "Constant", args);
1986                         }
1987
1988                         return base.CreateExpressionTree (ec);
1989                 }
1990
1991                 protected override Expression DoResolve (ResolveContext ec)
1992                 {
1993                         return this;
1994                 }
1995
1996                 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1997                 {
1998                         // Type it as string cast
1999                         if (targetType == TypeManager.object_type || targetType == InternalType.Null)
2000                                 enc.Encode (TypeManager.string_type);
2001
2002                         var ac = targetType as ArrayContainer;
2003                         if (ac != null) {
2004                                 if (ac.Rank != 1 || ac.Element.IsArray)
2005                                         base.EncodeAttributeValue (rc, enc, targetType);
2006                                 else
2007                                         enc.Stream.Write (uint.MaxValue);
2008                         } else {
2009                                 enc.Stream.Write (byte.MaxValue);
2010                         }
2011                 }
2012
2013                 public override void Emit (EmitContext ec)
2014                 {
2015                         ec.Emit (OpCodes.Ldnull);
2016
2017                         // Only to make verifier happy
2018                         if (TypeManager.IsGenericParameter (type))
2019                                 ec.Emit (OpCodes.Unbox_Any, type);
2020                 }
2021
2022                 public override string ExprClassName {
2023                         get {
2024                                 return GetSignatureForError ();
2025                         }
2026                 }
2027
2028                 public override string GetSignatureForError ()
2029                 {
2030                         return "null";
2031                 }
2032
2033                 public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2034                 {
2035                         if (targetType.IsPointer) {
2036                                 if (IsLiteral || this is NullPointer)
2037                                         return new EmptyConstantCast (new NullPointer (loc), targetType);
2038
2039                                 return null;
2040                         }
2041
2042                         // Exlude internal compiler types
2043                         if (targetType.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null)
2044                                 return null;
2045
2046                         if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2047                                 return null;
2048
2049                         if (TypeManager.IsReferenceType (targetType))
2050                                 return new NullConstant (targetType, loc);
2051
2052                         if (TypeManager.IsNullableType (targetType))
2053                                 return Nullable.LiftedNull.Create (targetType, loc);
2054
2055                         return null;
2056                 }
2057
2058                 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
2059                 {
2060                         return ConvertExplicitly (false, targetType);
2061                 }
2062
2063                 public override object GetValue ()
2064                 {
2065                         return null;
2066                 }
2067
2068                 public override bool IsDefaultValue {
2069                         get { return true; }
2070                 }
2071
2072                 public override bool IsNegative {
2073                         get { return false; }
2074                 }
2075
2076                 public override bool IsNull {
2077                         get { return true; }
2078                 }
2079
2080                 public override bool IsZeroInteger {
2081                         get { return true; }
2082                 }
2083         }
2084
2085         /// <summary>
2086         ///   The value is constant, but when emitted has a side effect.  This is
2087         ///   used by BitwiseAnd to ensure that the second expression is invoked
2088         ///   regardless of the value of the left side.  
2089         /// </summary>
2090         public class SideEffectConstant : Constant {
2091                 public Constant value;
2092                 Expression side_effect;
2093                 
2094                 public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
2095                 {
2096                         this.value = value;
2097                         while (side_effect is SideEffectConstant)
2098                                 side_effect = ((SideEffectConstant) side_effect).side_effect;
2099                         this.side_effect = side_effect;
2100                 }
2101
2102                 public override string AsString ()
2103                 {
2104                         return value.AsString ();
2105                 }
2106
2107                 protected override Expression DoResolve (ResolveContext rc)
2108                 {
2109                         value = value.Resolve (rc);
2110
2111                         type = value.Type;
2112                         eclass = ExprClass.Value;
2113                         return this;
2114                 }
2115
2116                 public override object GetValue ()
2117                 {
2118                         return value.GetValue ();
2119                 }
2120
2121                 public override void Emit (EmitContext ec)
2122                 {
2123                         side_effect.EmitSideEffect (ec);
2124                         value.Emit (ec);
2125                 }
2126
2127                 public override void EmitSideEffect (EmitContext ec)
2128                 {
2129                         side_effect.EmitSideEffect (ec);
2130                         value.EmitSideEffect (ec);
2131                 }
2132
2133                 public override bool IsDefaultValue {
2134                         get { return value.IsDefaultValue; }
2135                 }
2136
2137                 public override bool IsNegative {
2138                         get { return value.IsNegative; }
2139                 }
2140
2141                 public override bool IsZeroInteger {
2142                         get { return value.IsZeroInteger; }
2143                 }
2144
2145                 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2146                 {
2147                         Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2148                         return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);
2149                 }
2150         }
2151 }