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