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