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