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