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