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