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