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