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