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