Patch #60.
[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                         EmitLong (ec.ig, Value);
1362                 }
1363
1364                 static public void EmitLong (ILGenerator ig, long l)
1365                 {
1366                         if (l >= int.MinValue && l <= int.MaxValue) {
1367                                 IntLiteral.EmitInt (ig, unchecked ((int) l));
1368                                 ig.Emit (OpCodes.Conv_I8);
1369                                 return;
1370                         }
1371                         ig.Emit (OpCodes.Ldc_I8, l);
1372                 }
1373
1374                 public override string AsString ()
1375                 {
1376                         return Value.ToString ();
1377                 }
1378
1379                 public override object GetValue ()
1380                 {
1381                         return Value;
1382                 }
1383
1384                 public override DoubleConstant ConvertToDouble ()
1385                 {
1386                         return new DoubleConstant (Value, loc);
1387                 }
1388
1389                 public override FloatConstant ConvertToFloat ()
1390                 {
1391                         return new FloatConstant (Value, loc);
1392                 }
1393
1394                 public override ULongConstant ConvertToULong ()
1395                 {
1396                         if (Value < 0)
1397                                 return null;
1398                         
1399                         return new ULongConstant ((ulong) Value, loc);
1400                 }
1401
1402                 public override LongConstant ConvertToLong ()
1403                 {
1404                         return this;
1405                 }
1406
1407                 public override UIntConstant ConvertToUInt ()
1408                 {
1409                         return null;
1410                 }
1411
1412                 public override IntConstant ConvertToInt ()
1413                 {
1414                         return null;
1415                 }
1416
1417                 public override Constant Increment ()
1418                 {
1419                         return new LongConstant (checked(Value + 1), loc);
1420                 }
1421                 
1422                 public override bool IsDefaultValue {
1423                         get {
1424                                 return Value == 0;
1425                         }
1426                 }
1427
1428                 public override bool IsNegative {
1429                         get {
1430                                 return Value < 0;
1431                         }
1432                 }
1433
1434                 public override bool IsZeroInteger {
1435                         get { return Value == 0; }
1436                 }
1437
1438                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1439                 {
1440                         if (target_type == TypeManager.byte_type) {
1441                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1442                                 return new ByteConstant ((byte) Value, Location);
1443                         }
1444                         if (target_type == TypeManager.sbyte_type) {
1445                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1446                                 return new SByteConstant ((sbyte) Value, Location);
1447                         }
1448                         if (target_type == TypeManager.short_type) {
1449                                 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1450                                 return new ShortConstant ((short) Value, Location);
1451                         }
1452                         if (target_type == TypeManager.ushort_type) {
1453                                 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1454                                 return new UShortConstant ((ushort) Value, Location);
1455                         }
1456                         if (target_type == TypeManager.int32_type) {
1457                                 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1458                                 return new IntConstant ((int) Value, Location);
1459                         }
1460                         if (target_type == TypeManager.uint32_type) {
1461                                 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1462                                 return new UIntConstant ((uint) Value, Location);
1463                         }
1464                         if (target_type == TypeManager.uint64_type) {
1465                                 CheckUnsigned (inCheckedContext, Value);
1466                                 return new ULongConstant ((ulong) Value, Location);
1467                         }
1468                         if (target_type == TypeManager.float_type)
1469                                 return new FloatConstant ((float) Value, Location);
1470                         if (target_type == TypeManager.double_type)
1471                                 return new DoubleConstant ((double) Value, Location);
1472                         if (target_type == TypeManager.char_type) {
1473                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1474                                 return new CharConstant ((char) Value, Location);
1475                         }
1476                         if (target_type == TypeManager.decimal_type)
1477                                 return new DecimalConstant ((decimal) Value, Location);
1478
1479                         return null;
1480                 }
1481
1482         }
1483
1484         public class ULongConstant : IntegralConstant {
1485                 public readonly ulong Value;
1486
1487                 public ULongConstant (ulong v, Location loc):
1488                         base (loc)
1489                 {
1490                         type = TypeManager.uint64_type;
1491                         eclass = ExprClass.Value;
1492                         Value = v;
1493                 }
1494
1495                 public override void Emit (EmitContext ec)
1496                 {
1497                         ILGenerator ig = ec.ig;
1498
1499                         LongLiteral.EmitLong (ig, unchecked ((long) Value));
1500                 }
1501
1502                 public override string AsString ()
1503                 {
1504                         return Value.ToString ();
1505                 }
1506
1507                 public override object GetValue ()
1508                 {
1509                         return Value;
1510                 }
1511
1512                 public override DoubleConstant ConvertToDouble ()
1513                 {
1514                         return new DoubleConstant (Value, loc);
1515                 }
1516
1517                 public override FloatConstant ConvertToFloat ()
1518                 {
1519                         return new FloatConstant (Value, loc);
1520                 }
1521
1522                 public override ULongConstant ConvertToULong ()
1523                 {
1524                         return this;
1525                 }
1526
1527                 public override LongConstant ConvertToLong ()
1528                 {
1529                         return null;
1530                 }
1531
1532                 public override UIntConstant ConvertToUInt ()
1533                 {
1534                         return null;
1535                 }
1536
1537                 public override IntConstant ConvertToInt ()
1538                 {
1539                         return null;
1540                 }
1541
1542                 public override Constant Increment ()
1543                 {
1544                         return new ULongConstant (checked(Value + 1), loc);
1545                 }
1546
1547                 public override bool IsDefaultValue {
1548                         get {
1549                                 return Value == 0;
1550                         }
1551                 }
1552
1553                 public override bool IsNegative {
1554                         get {
1555                                 return false;
1556                         }
1557                 }
1558
1559                 public override bool IsZeroInteger {
1560                         get { return Value == 0; }
1561                 }
1562
1563                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1564                 {
1565                         if (target_type == TypeManager.byte_type) {
1566                                 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1567                                 return new ByteConstant ((byte) Value, Location);
1568                         }
1569                         if (target_type == TypeManager.sbyte_type) {
1570                                 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1571                                 return new SByteConstant ((sbyte) Value, Location);
1572                         }
1573                         if (target_type == TypeManager.short_type) {
1574                                 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1575                                 return new ShortConstant ((short) Value, Location);
1576                         }
1577                         if (target_type == TypeManager.ushort_type) {
1578                                 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1579                                 return new UShortConstant ((ushort) Value, Location);
1580                         }
1581                         if (target_type == TypeManager.int32_type) {
1582                                 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1583                                 return new IntConstant ((int) Value, Location);
1584                         }
1585                         if (target_type == TypeManager.uint32_type) {
1586                                 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1587                                 return new UIntConstant ((uint) Value, Location);
1588                         }
1589                         if (target_type == TypeManager.int64_type) {
1590                                 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1591                                 return new LongConstant ((long) Value, Location);
1592                         }
1593                         if (target_type == TypeManager.float_type)
1594                                 return new FloatConstant ((float) Value, Location);
1595                         if (target_type == TypeManager.double_type)
1596                                 return new DoubleConstant ((double) Value, Location);
1597                         if (target_type == TypeManager.char_type) {
1598                                 CheckRange (inCheckedContext, Value, Char.MaxValue);
1599                                 return new CharConstant ((char) Value, Location);
1600                         }
1601                         if (target_type == TypeManager.decimal_type)
1602                                 return new DecimalConstant ((decimal) Value, Location);
1603
1604                         return null;
1605                 }
1606
1607         }
1608
1609         public class FloatConstant : Constant {
1610                 public readonly float Value;
1611
1612                 public FloatConstant (float v, Location loc):
1613                         base (loc)
1614                 {
1615                         type = TypeManager.float_type;
1616                         eclass = ExprClass.Value;
1617                         Value = v;
1618                 }
1619
1620                 public override void Emit (EmitContext ec)
1621                 {
1622                         ec.ig.Emit (OpCodes.Ldc_R4, Value);
1623                 }
1624
1625                 public override string AsString ()
1626                 {
1627                         return Value.ToString ();
1628                 }
1629
1630                 public override object GetValue ()
1631                 {
1632                         return Value;
1633                 }
1634
1635                 public override DoubleConstant ConvertToDouble ()
1636                 {
1637                         return new DoubleConstant (Value, loc);
1638                 }
1639
1640                 public override FloatConstant ConvertToFloat ()
1641                 {
1642                         return this;
1643                 }
1644
1645                 public override LongConstant ConvertToLong ()
1646                 {
1647                         return null;
1648                 }
1649
1650                 public override UIntConstant ConvertToUInt ()
1651                 {
1652                         return null;
1653                 }
1654
1655                 public override IntConstant ConvertToInt ()
1656                 {
1657                         return null;
1658                 }
1659
1660                 public override Constant Increment ()
1661                 {
1662                         return new FloatConstant (checked(Value + 1), loc);
1663                 }
1664
1665                 public override bool IsDefaultValue {
1666                         get {
1667                                 return Value == 0;
1668                         }
1669                 }
1670
1671                 public override bool IsNegative {
1672                         get {
1673                                 return Value < 0;
1674                         }
1675                 }
1676
1677                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1678                 {
1679                         if (target_type == TypeManager.byte_type) {
1680                                 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1681                                 return new ByteConstant ((byte) Value, Location);
1682                         }
1683                         if (target_type == TypeManager.sbyte_type) {
1684                                 CheckRange (inCheckedContext, Value,  sbyte.MinValue, sbyte.MaxValue);
1685                                 return new SByteConstant ((sbyte) Value, Location);
1686                         }
1687                         if (target_type == TypeManager.short_type) {
1688                                 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1689                                 return new ShortConstant ((short) Value, Location);
1690                         }
1691                         if (target_type == TypeManager.ushort_type) {
1692                                 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1693                                 return new UShortConstant ((ushort) Value, Location);
1694                         }
1695                         if (target_type == TypeManager.int32_type) {
1696                                 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1697                                 return new IntConstant ((int) Value, Location);
1698                         }
1699                         if (target_type == TypeManager.uint32_type) {
1700                                 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1701                                 return new UIntConstant ((uint) Value, Location);
1702                         }
1703                         if (target_type == TypeManager.int64_type) {
1704                                 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1705                                 return new LongConstant ((long) Value, Location);
1706                         }
1707                         if (target_type == TypeManager.uint64_type) {
1708                                 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1709                                 return new ULongConstant ((ulong) Value, Location);
1710                         }
1711                         if (target_type == TypeManager.double_type)
1712                                 return new DoubleConstant ((double) Value, Location);
1713                         if (target_type == TypeManager.char_type) {
1714                                 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1715                                 return new CharConstant ((char) Value, Location);
1716                         }
1717                         if (target_type == TypeManager.decimal_type)
1718                                 return new DecimalConstant ((decimal) Value, Location);
1719
1720                         return null;
1721                 }
1722
1723         }
1724
1725         public class DoubleConstant : Constant {
1726                 public readonly double Value;
1727
1728                 public DoubleConstant (double v, Location loc):
1729                         base (loc)
1730                 {
1731                         type = TypeManager.double_type;
1732                         eclass = ExprClass.Value;
1733                         Value = v;
1734                 }
1735
1736                 public override void Emit (EmitContext ec)
1737                 {
1738                         ec.ig.Emit (OpCodes.Ldc_R8, Value);
1739                 }
1740
1741                 public override string AsString ()
1742                 {
1743                         return Value.ToString ();
1744                 }
1745
1746                 public override object GetValue ()
1747                 {
1748                         return Value;
1749                 }
1750
1751                 public override DoubleConstant ConvertToDouble ()
1752                 {
1753                         return this;
1754                 }
1755
1756                 public override FloatConstant ConvertToFloat ()
1757                 {
1758                         return null;
1759                 }
1760
1761                 public override ULongConstant ConvertToULong ()
1762                 {
1763                         return null;
1764                 }
1765
1766                 public override LongConstant ConvertToLong ()
1767                 {
1768                         return null;
1769                 }
1770
1771                 public override UIntConstant ConvertToUInt ()
1772                 {
1773                         return null;
1774                 }
1775
1776                 public override IntConstant ConvertToInt ()
1777                 {
1778                         return null;
1779                 }
1780
1781                 public override Constant Increment ()
1782                 {
1783                         return new DoubleConstant (checked(Value + 1), loc);
1784                 }
1785
1786                 public override bool IsDefaultValue {
1787                         get {
1788                                 return Value == 0;
1789                         }
1790                 }
1791
1792                 public override bool IsNegative {
1793                         get {
1794                                 return Value < 0;
1795                         }
1796                 }
1797
1798                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1799                 {
1800                         if (target_type == TypeManager.byte_type) {
1801                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1802                                 return new ByteConstant ((byte) Value, Location);
1803                         }
1804                         if (target_type == TypeManager.sbyte_type) {
1805                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1806                                 return new SByteConstant ((sbyte) Value, Location);
1807                         }
1808                         if (target_type == TypeManager.short_type) {
1809                                 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1810                                 return new ShortConstant ((short) Value, Location);
1811                         }
1812                         if (target_type == TypeManager.ushort_type) {
1813                                 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1814                                 return new UShortConstant ((ushort) Value, Location);
1815                         }
1816                         if (target_type == TypeManager.int32_type) {
1817                                 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1818                                 return new IntConstant ((int) Value, Location);
1819                         }
1820                         if (target_type == TypeManager.uint32_type) {
1821                                 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1822                                 return new UIntConstant ((uint) Value, Location);
1823                         }
1824                         if (target_type == TypeManager.int64_type) {
1825                                 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1826                                 return new LongConstant ((long) Value, Location);
1827                         }
1828                         if (target_type == TypeManager.uint64_type) {
1829                                 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1830                                 return new ULongConstant ((ulong) Value, Location);
1831                         }
1832                         if (target_type == TypeManager.float_type)
1833                                 return new FloatConstant ((float) Value, Location);
1834                         if (target_type == TypeManager.char_type) {
1835                                 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1836                                 return new CharConstant ((char) Value, Location);
1837                         }
1838                         if (target_type == TypeManager.decimal_type)
1839                                 return new DecimalConstant ((decimal) Value, Location);
1840
1841                         return null;
1842                 }
1843
1844         }
1845
1846         public class DecimalConstant : Constant {
1847                 public readonly decimal Value;
1848
1849                 public DecimalConstant (decimal d, Location loc):
1850                         base (loc)
1851                 {
1852                         type = TypeManager.decimal_type;
1853                         eclass = ExprClass.Value;
1854                         Value = d;
1855                 }
1856
1857                 override public string AsString ()
1858                 {
1859                         return Value.ToString ();
1860                 }
1861
1862                 public override object GetValue ()
1863                 {
1864                         return (object) Value;
1865                 }
1866
1867                 public override void Emit (EmitContext ec)
1868                 {
1869                         ILGenerator ig = ec.ig;
1870
1871                         int [] words = Decimal.GetBits (Value);
1872                         int power = (words [3] >> 16) & 0xff;
1873
1874                         if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1875                         {
1876                                 IntConstant.EmitInt (ig, (int)Value);
1877                                 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1878                                 return;
1879                         }
1880
1881                         
1882                         //
1883                         // FIXME: we could optimize this, and call a better 
1884                         // constructor
1885                         //
1886
1887                         IntConstant.EmitInt (ig, words [0]);
1888                         IntConstant.EmitInt (ig, words [1]);
1889                         IntConstant.EmitInt (ig, words [2]);
1890
1891                         // sign
1892                         IntConstant.EmitInt (ig, words [3] >> 31);
1893
1894                         // power
1895                         IntConstant.EmitInt (ig, power);
1896
1897                         ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1898                 }
1899
1900                 public override Constant Increment ()
1901                 {
1902                         return new DecimalConstant (checked (Value + 1), loc);
1903                 }
1904
1905                 public override bool IsDefaultValue {
1906                         get {
1907                                 return Value == 0;
1908                         }
1909                 }
1910
1911                 public override bool IsNegative {
1912                         get {
1913                                 return Value < 0;
1914                         }
1915                 }
1916
1917                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1918                 {
1919                         if (target_type == TypeManager.sbyte_type)
1920                                 return new SByteConstant ((sbyte)Value, loc);
1921                         if (target_type == TypeManager.byte_type)
1922                                 return new ByteConstant ((byte)Value, loc);
1923                         if (target_type == TypeManager.short_type)
1924                                 return new ShortConstant ((short)Value, loc);
1925                         if (target_type == TypeManager.ushort_type)
1926                                 return new UShortConstant ((ushort)Value, loc);
1927                         if (target_type == TypeManager.int32_type)
1928                                 return new IntConstant ((int)Value, loc);
1929                         if (target_type == TypeManager.uint32_type)
1930                                 return new UIntConstant ((uint)Value, loc);
1931                         if (target_type == TypeManager.int64_type)
1932                                 return new LongConstant ((long)Value, loc);
1933                         if (target_type == TypeManager.uint64_type)
1934                                 return new ULongConstant ((ulong)Value, loc);
1935                         if (target_type == TypeManager.char_type)
1936                                 return new CharConstant ((char)Value, loc);
1937                         if (target_type == TypeManager.float_type)
1938                                 return new FloatConstant ((float)Value, loc);
1939                         if (target_type == TypeManager.double_type)
1940                                 return new DoubleConstant ((double)Value, loc);
1941
1942                         return null;
1943                 }
1944
1945         }
1946
1947         public class StringConstant : Constant {
1948                 public readonly string Value;
1949
1950                 public StringConstant (string s, Location loc):
1951                         base (loc)
1952                 {
1953                         type = TypeManager.string_type;
1954                         eclass = ExprClass.Value;
1955                         Value = s;
1956                 }
1957
1958                 // FIXME: Escape the string.
1959                 override public string AsString ()
1960                 {
1961                         return "\"" + Value + "\"";
1962                 }
1963
1964                 public override object GetValue ()
1965                 {
1966                         return Value;
1967                 }
1968                 
1969                 public override void Emit (EmitContext ec)
1970                 {
1971                         if (Value == null)
1972                                 ec.ig.Emit (OpCodes.Ldnull);
1973                         else
1974                                 ec.ig.Emit (OpCodes.Ldstr, Value);
1975                 }
1976
1977                 public override Constant Increment ()
1978                 {
1979                         throw new NotSupportedException ();
1980                 }
1981
1982                 public override bool IsDefaultValue {
1983                         get {
1984                                 return Value == null;
1985                         }
1986                 }
1987
1988                 public override bool IsNegative {
1989                         get {
1990                                 return false;
1991                         }
1992                 }
1993
1994                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1995                 {
1996                         return null;
1997                 }
1998         }
1999
2000 }
2001
2002