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