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