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