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