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