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