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