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