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