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