Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/constant.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 64.0 KB
Line 
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
13using System;
14using System.Globalization;
15
16#if STATIC
17using IKVM.Reflection.Emit;
18#else
19using System.Reflection.Emit;
20#endif
21
22namespace Mono.CSharp {
23
24  /// <summary>
25  ///   Base class for constants and literals.
26  /// </summary>
27  public abstract class Constant : Expression
28  {
29    static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
30
31    protected Constant (Location loc)
32    {
33      this.loc = loc;
34    }
35
36    override public string ToString ()
37    {
38      return this.GetType ().Name + " (" + GetValueAsLiteral () + ")";
39    }
40
41    /// <summary>
42    ///  This is used to obtain the actual value of the literal
43    ///  cast into an object.
44    /// </summary>
45    public abstract object GetValue ();
46
47    public abstract long GetValueAsLong ();
48
49    public abstract string GetValueAsLiteral ();
50
51#if !STATIC
52    //
53    // Returns an object value which is typed to contant type
54    //
55    public virtual object GetTypedValue ()
56    {
57      return GetValue ();
58    }
59#endif
60
61    public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
62    {
63      if (!expl && IsLiteral &&
64        BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
65        BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) {
66        ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
67          GetValueAsLiteral (), target.GetSignatureForError ());
68      } else {
69        base.Error_ValueCannotBeConverted (ec, target, expl);
70      }
71    }
72
73    public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type)
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    public override object Accept (StructuralVisitor visitor)
463    {
464      return visitor.Visit (this);
465    }
466
467  }
468
469  public abstract class IntegralConstant : Constant
470  {
471    protected IntegralConstant (TypeSpec type, Location loc)
472      : base (loc)
473    {
474      this.type = type;
475      eclass = ExprClass.Value;
476    }
477
478    public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
479    {
480      try {
481        ConvertExplicitly (true, target);
482        base.Error_ValueCannotBeConverted (ec, target, expl);
483      }
484      catch
485      {
486        ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
487          GetValue ().ToString (), target.GetSignatureForError ());
488      }
489    }
490
491    public override string GetValueAsLiteral ()
492    {
493      return GetValue ().ToString ();
494    }
495   
496    public abstract Constant Increment ();
497  }
498 
499  public class BoolConstant : Constant {
500    public readonly bool Value;
501
502    public BoolConstant (BuiltinTypes types, bool val, Location loc)
503      : this (types.Bool, val, loc)
504    {
505    }
506   
507    public BoolConstant (TypeSpec type, bool val, Location loc)
508      : base (loc)
509    {
510      eclass = ExprClass.Value;
511      this.type = type;
512
513      Value = val;
514    }
515
516    public override object GetValue ()
517    {
518      return (object) Value;
519    }
520
521    public override string GetValueAsLiteral ()
522    {
523      return Value ? "true" : "false";
524    }
525
526    public override long GetValueAsLong ()
527    {
528      return Value ? 1 : 0;
529    }
530
531    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
532    {
533      enc.Encode (Value);
534    }
535   
536    public override void Emit (EmitContext ec)
537    {
538      if (Value)
539        ec.EmitInt (1);
540      else
541        ec.EmitInt (0);
542    }
543
544    public override bool IsDefaultValue {
545      get {
546        return !Value;
547      }
548    }
549
550    public override bool IsNegative {
551      get {
552        return false;
553      }
554    }
555 
556    public override bool IsZeroInteger {
557      get { return Value == false; }
558    }
559
560    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
561    {
562      return null;
563    }
564
565  }
566
567  public class ByteConstant : IntegralConstant
568  {
569    public readonly byte Value;
570
571    public ByteConstant (BuiltinTypes types, byte v, Location loc)
572      : this (types.Byte, v, loc)
573    {
574    }
575
576    public ByteConstant (TypeSpec type, byte v, Location loc)
577      : base (type, loc)
578    {
579      Value = v;
580    }
581
582    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
583    {
584      enc.Encode (Value);
585    }
586
587    public override void Emit (EmitContext ec)
588    {
589      ec.EmitInt (Value);
590    }
591
592    public override object GetValue ()
593    {
594      return Value;
595    }
596
597    public override long GetValueAsLong ()
598    {
599      return Value;
600    }
601
602    public override Constant Increment ()
603    {
604      return new ByteConstant (type, checked ((byte)(Value + 1)), loc);
605    }
606
607    public override bool IsDefaultValue {
608      get {
609        return Value == 0;
610      }
611    }
612
613    public override bool IsOneInteger {
614      get {
615        return Value == 1;
616      }
617    }   
618
619    public override bool IsNegative {
620      get {
621        return false;
622      }
623    }
624
625    public override bool IsZeroInteger {
626      get { return Value == 0; }
627    }
628
629    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
630    {
631      switch (target_type.BuiltinType) {
632      case BuiltinTypeSpec.Type.SByte:
633        if (in_checked_context){
634          if (Value > SByte.MaxValue)
635            throw new OverflowException ();
636        }
637        return new SByteConstant (target_type, (sbyte) Value, Location);
638      case BuiltinTypeSpec.Type.Short:
639        return new ShortConstant (target_type, (short) Value, Location);
640      case BuiltinTypeSpec.Type.UShort:
641        return new UShortConstant (target_type, (ushort) Value, Location);
642      case BuiltinTypeSpec.Type.Int:
643        return new IntConstant (target_type, (int) Value, Location);
644      case BuiltinTypeSpec.Type.UInt:
645        return new UIntConstant (target_type, (uint) Value, Location);
646      case BuiltinTypeSpec.Type.Long:
647        return new LongConstant (target_type, (long) Value, Location);
648      case BuiltinTypeSpec.Type.ULong:
649        return new ULongConstant (target_type, (ulong) Value, Location);
650      case BuiltinTypeSpec.Type.Float:
651        return new FloatConstant (target_type, (float) Value, Location);
652      case BuiltinTypeSpec.Type.Double:
653        return new DoubleConstant (target_type, (double) Value, Location);
654      case BuiltinTypeSpec.Type.Char:
655        return new CharConstant (target_type, (char) Value, Location);
656      case BuiltinTypeSpec.Type.Decimal:
657        return new DecimalConstant (target_type, (decimal) Value, Location);
658      }
659
660      return null;
661    }
662
663  }
664
665  public class CharConstant : Constant {
666    public readonly char Value;
667
668    public CharConstant (BuiltinTypes types, char v, Location loc)
669      : this (types.Char, v, loc)
670    {
671    }
672
673    public CharConstant (TypeSpec type, char v, Location loc)
674      : base (loc)
675    {
676      this.type = type;
677      eclass = ExprClass.Value;
678
679      Value = v;
680    }
681
682    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
683    {
684      enc.Encode ((ushort) Value);
685    }
686
687    public override void Emit (EmitContext ec)
688    {
689      ec.EmitInt (Value);
690    }
691
692    static string descape (char c)
693    {
694      switch (c){
695      case '\a':
696        return "\\a";
697      case '\b':
698        return "\\b";
699      case '\n':
700        return "\\n";
701      case '\t':
702        return "\\t";
703      case '\v':
704        return "\\v";
705      case '\r':
706        return "\\r";
707      case '\\':
708        return "\\\\";
709      case '\f':
710        return "\\f";
711      case '\0':
712        return "\\0";
713      case '"':
714        return "\\\"";
715      case '\'':
716        return "\\\'";
717      }
718      return c.ToString ();
719    }
720
721    public override object GetValue ()
722    {
723      return Value;
724    }
725
726    public override long GetValueAsLong ()
727    {
728      return Value;
729    }
730
731    public override string GetValueAsLiteral ()
732    {
733      return "\"" + descape (Value) + "\"";
734    }
735
736    public override bool IsDefaultValue {
737      get {
738        return Value == 0;
739      }
740    }
741
742    public override bool IsNegative {
743      get {
744        return false;
745      }
746    }
747
748    public override bool IsZeroInteger {
749      get { return Value == '\0'; }
750    }
751
752    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
753    {
754      switch (target_type.BuiltinType) {
755      case BuiltinTypeSpec.Type.Byte:
756        if (in_checked_context) {
757          if (Value < Byte.MinValue || Value > Byte.MaxValue)
758            throw new OverflowException ();
759        }
760        return new ByteConstant (target_type, (byte) Value, Location);
761      case BuiltinTypeSpec.Type.SByte:
762        if (in_checked_context) {
763          if (Value > SByte.MaxValue)
764            throw new OverflowException ();
765        }
766        return new SByteConstant (target_type, (sbyte) Value, Location);
767
768      case BuiltinTypeSpec.Type.Short:
769        if (in_checked_context) {
770          if (Value > Int16.MaxValue)
771            throw new OverflowException ();
772        }
773        return new ShortConstant (target_type, (short) Value, Location);
774      case BuiltinTypeSpec.Type.Int:
775        return new IntConstant (target_type, (int) Value, Location);
776      case BuiltinTypeSpec.Type.UInt:
777        return new UIntConstant (target_type, (uint) Value, Location);
778      case BuiltinTypeSpec.Type.Long:
779        return new LongConstant (target_type, (long) Value, Location);
780      case BuiltinTypeSpec.Type.ULong:
781        return new ULongConstant (target_type, (ulong) Value, Location);
782      case BuiltinTypeSpec.Type.Float:
783        return new FloatConstant (target_type, (float) Value, Location);
784      case BuiltinTypeSpec.Type.Double:
785        return new DoubleConstant (target_type, (double) Value, Location);
786      case BuiltinTypeSpec.Type.Decimal:
787        return new DecimalConstant (target_type, (decimal) Value, Location);
788      }
789
790      return null;
791    }
792
793  }
794
795  public class SByteConstant : IntegralConstant
796  {
797    public readonly sbyte Value;
798
799    public SByteConstant (BuiltinTypes types, sbyte v, Location loc)
800      : this (types.SByte, v, loc)
801    {
802    }
803
804    public SByteConstant (TypeSpec type, sbyte v, Location loc)
805      : base (type, loc)
806    {
807      Value = v;
808    }
809
810    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
811    {
812      enc.Encode (Value);
813    }
814
815    public override void Emit (EmitContext ec)
816    {
817      ec.EmitInt (Value);
818    }
819
820    public override object GetValue ()
821    {
822      return Value;
823    }
824
825    public override long GetValueAsLong ()
826    {
827      return Value;
828    }
829
830    public override Constant Increment ()
831    {
832        return new SByteConstant (type, checked((sbyte)(Value + 1)), loc);
833    }
834
835    public override bool IsDefaultValue {
836      get {
837        return Value == 0;
838      }
839    }
840
841    public override bool IsNegative {
842      get {
843        return Value < 0;
844      }
845    }
846   
847    public override bool IsOneInteger {
848      get {
849        return Value == 1;
850      }
851    }   
852   
853    public override bool IsZeroInteger {
854      get { return Value == 0; }
855    }
856
857    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
858    {
859      switch (target_type.BuiltinType) {
860      case BuiltinTypeSpec.Type.Byte:
861        if (in_checked_context && Value < 0)
862          throw new OverflowException ();
863        return new ByteConstant (target_type, (byte) Value, Location);
864      case BuiltinTypeSpec.Type.Short:
865        return new ShortConstant (target_type, (short) Value, Location);
866      case BuiltinTypeSpec.Type.UShort:
867        if (in_checked_context && Value < 0)
868          throw new OverflowException ();
869        return new UShortConstant (target_type, (ushort) Value, Location);
870      case BuiltinTypeSpec.Type.Int:
871        return new IntConstant (target_type, (int) Value, Location);
872      case BuiltinTypeSpec.Type.UInt:
873        if (in_checked_context && Value < 0)
874          throw new OverflowException ();
875        return new UIntConstant (target_type, (uint) Value, Location);
876      case BuiltinTypeSpec.Type.Long:
877        return new LongConstant (target_type, (long) Value, Location);
878      case BuiltinTypeSpec.Type.ULong:
879        if (in_checked_context && Value < 0)
880          throw new OverflowException ();
881        return new ULongConstant (target_type, (ulong) Value, Location);
882      case BuiltinTypeSpec.Type.Float:
883        return new FloatConstant (target_type, (float) Value, Location);
884      case BuiltinTypeSpec.Type.Double:
885        return new DoubleConstant (target_type, (double) Value, Location);
886      case BuiltinTypeSpec.Type.Char:
887        if (in_checked_context && Value < 0)
888          throw new OverflowException ();
889        return new CharConstant (target_type, (char) Value, Location);
890      case BuiltinTypeSpec.Type.Decimal:
891        return new DecimalConstant (target_type, (decimal) Value, Location);
892      }
893
894      return null;
895    }
896
897  }
898
899  public class ShortConstant : IntegralConstant {
900    public readonly short Value;
901
902    public ShortConstant (BuiltinTypes types, short v, Location loc)
903      : this (types.Short, v, loc)
904    {
905    }
906
907    public ShortConstant (TypeSpec type, short v, Location loc)
908      : base (type, loc)
909    {
910      Value = v;
911    }
912
913    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
914    {
915      enc.Encode (Value);
916    }
917
918    public override void Emit (EmitContext ec)
919    {
920      ec.EmitInt (Value);
921    }
922
923    public override object GetValue ()
924    {
925      return Value;
926    }
927
928    public override long GetValueAsLong ()
929    {
930      return Value;
931    }
932
933    public override Constant Increment ()
934    {
935      return new ShortConstant (type, checked((short)(Value + 1)), loc);
936    }
937
938    public override bool IsDefaultValue {
939      get {
940        return Value == 0;
941      }
942    }
943   
944    public override bool IsZeroInteger {
945      get { return Value == 0; }
946    }
947
948    public override bool IsNegative {
949      get {
950        return Value < 0;
951      }
952    }
953   
954    public override bool IsOneInteger {
955      get {
956        return Value == 1;
957      }
958    }   
959
960    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
961    {
962      switch (target_type.BuiltinType) {
963      case BuiltinTypeSpec.Type.Byte:
964        if (in_checked_context) {
965          if (Value < Byte.MinValue || Value > Byte.MaxValue)
966            throw new OverflowException ();
967        }
968        return new ByteConstant (target_type, (byte) Value, Location);
969      case BuiltinTypeSpec.Type.SByte:
970        if (in_checked_context) {
971          if (Value < SByte.MinValue || Value > SByte.MaxValue)
972            throw new OverflowException ();
973        }
974        return new SByteConstant (target_type, (sbyte) Value, Location);
975      case BuiltinTypeSpec.Type.UShort:
976        if (in_checked_context && Value < 0)
977          throw new OverflowException ();
978
979        return new UShortConstant (target_type, (ushort) Value, Location);
980      case BuiltinTypeSpec.Type.Int:
981        return new IntConstant (target_type, (int) Value, Location);
982      case BuiltinTypeSpec.Type.UInt:
983        if (in_checked_context && Value < 0)
984          throw new OverflowException ();
985        return new UIntConstant (target_type, (uint) Value, Location);
986      case BuiltinTypeSpec.Type.Long:
987        return new LongConstant (target_type, (long) Value, Location);
988      case BuiltinTypeSpec.Type.ULong:
989        if (in_checked_context && Value < 0)
990          throw new OverflowException ();
991        return new ULongConstant (target_type, (ulong) Value, Location);
992      case BuiltinTypeSpec.Type.Float:
993        return new FloatConstant (target_type, (float) Value, Location);
994      case BuiltinTypeSpec.Type.Double:
995        return new DoubleConstant (target_type, (double) Value, Location);
996      case BuiltinTypeSpec.Type.Char:
997        if (in_checked_context) {
998          if (Value < Char.MinValue)
999            throw new OverflowException ();
1000        }
1001        return new CharConstant (target_type, (char) Value, Location);
1002      case BuiltinTypeSpec.Type.Decimal:
1003        return new DecimalConstant (target_type, (decimal) Value, Location);
1004      }
1005
1006      return null;
1007    }
1008
1009  }
1010
1011  public class UShortConstant : IntegralConstant
1012  {
1013    public readonly ushort Value;
1014
1015    public UShortConstant (BuiltinTypes types, ushort v, Location loc)
1016      : this (types.UShort, v, loc)
1017    {
1018    }
1019
1020    public UShortConstant (TypeSpec type, ushort v, Location loc)
1021      : base (type, loc)
1022    {
1023      Value = v;
1024    }
1025
1026    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1027    {
1028      enc.Encode (Value);
1029    }
1030
1031    public override void Emit (EmitContext ec)
1032    {
1033      ec.EmitInt (Value);
1034    }
1035
1036    public override object GetValue ()
1037    {
1038      return Value;
1039    }
1040
1041    public override long GetValueAsLong ()
1042    {
1043      return Value;
1044    }
1045 
1046    public override Constant Increment ()
1047    {
1048      return new UShortConstant (type, checked((ushort)(Value + 1)), loc);
1049    }
1050
1051    public override bool IsDefaultValue {
1052      get {
1053        return Value == 0;
1054      }
1055    }
1056
1057    public override bool IsNegative {
1058      get {
1059        return false;
1060      }
1061    }
1062   
1063    public override bool IsOneInteger {
1064      get {
1065        return Value == 1;
1066      }
1067    }   
1068 
1069    public override bool IsZeroInteger {
1070      get { return Value == 0; }
1071    }
1072
1073    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1074    {
1075      switch (target_type.BuiltinType) {
1076      case BuiltinTypeSpec.Type.Byte:
1077        if (in_checked_context) {
1078          if (Value > Byte.MaxValue)
1079            throw new OverflowException ();
1080        }
1081        return new ByteConstant (target_type, (byte) Value, Location);
1082      case BuiltinTypeSpec.Type.SByte:
1083        if (in_checked_context) {
1084          if (Value > SByte.MaxValue)
1085            throw new OverflowException ();
1086        }
1087        return new SByteConstant (target_type, (sbyte) Value, Location);
1088      case BuiltinTypeSpec.Type.Short:
1089        if (in_checked_context) {
1090          if (Value > Int16.MaxValue)
1091            throw new OverflowException ();
1092        }
1093        return new ShortConstant (target_type, (short) Value, Location);
1094      case BuiltinTypeSpec.Type.Int:
1095        return new IntConstant (target_type, (int) Value, Location);
1096      case BuiltinTypeSpec.Type.UInt:
1097        return new UIntConstant (target_type, (uint) Value, Location);
1098      case BuiltinTypeSpec.Type.Long:
1099        return new LongConstant (target_type, (long) Value, Location);
1100      case BuiltinTypeSpec.Type.ULong:
1101        return new ULongConstant (target_type, (ulong) Value, Location);
1102      case BuiltinTypeSpec.Type.Float:
1103        return new FloatConstant (target_type, (float) Value, Location);
1104      case BuiltinTypeSpec.Type.Double:
1105        return new DoubleConstant (target_type, (double) Value, Location);
1106      case BuiltinTypeSpec.Type.Char:
1107        if (in_checked_context) {
1108          if (Value > Char.MaxValue)
1109            throw new OverflowException ();
1110        }
1111        return new CharConstant (target_type, (char) Value, Location);
1112      case BuiltinTypeSpec.Type.Decimal:
1113        return new DecimalConstant (target_type, (decimal) Value, Location);
1114      }
1115
1116      return null;
1117    }
1118  }
1119
1120  public class IntConstant : IntegralConstant
1121  {
1122    public readonly int Value;
1123
1124    public IntConstant (BuiltinTypes types, int v, Location loc)
1125      : this (types.Int, v, loc)
1126    {
1127    }
1128
1129    public IntConstant (TypeSpec type, int v, Location loc)
1130      : base (type, loc)
1131    {
1132      Value = v;
1133    }
1134
1135    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1136    {
1137      enc.Encode (Value);
1138    }
1139
1140    public override void Emit (EmitContext ec)
1141    {
1142      ec.EmitInt (Value);
1143    }
1144
1145    public override object GetValue ()
1146    {
1147      return Value;
1148    }
1149
1150    public override long GetValueAsLong ()
1151    {
1152      return Value;
1153    }
1154
1155    public override Constant Increment ()
1156    {
1157      return new IntConstant (type, checked(Value + 1), loc);
1158    }
1159
1160    public override bool IsDefaultValue {
1161      get {
1162        return Value == 0;
1163      }
1164    }
1165   
1166    public override bool IsNegative {
1167      get {
1168        return Value < 0;
1169      }
1170    }
1171   
1172    public override bool IsOneInteger {
1173      get {
1174        return Value == 1;
1175      }
1176    }   
1177
1178    public override bool IsZeroInteger {
1179      get { return Value == 0; }
1180    }
1181
1182    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1183    {
1184      switch (target_type.BuiltinType) {
1185      case BuiltinTypeSpec.Type.Byte:
1186        if (in_checked_context) {
1187          if (Value < Byte.MinValue || Value > Byte.MaxValue)
1188            throw new OverflowException ();
1189        }
1190        return new ByteConstant (target_type, (byte) Value, Location);
1191      case BuiltinTypeSpec.Type.SByte:
1192        if (in_checked_context) {
1193          if (Value < SByte.MinValue || Value > SByte.MaxValue)
1194            throw new OverflowException ();
1195        }
1196        return new SByteConstant (target_type, (sbyte) Value, Location);
1197      case BuiltinTypeSpec.Type.Short:
1198        if (in_checked_context) {
1199          if (Value < Int16.MinValue || Value > Int16.MaxValue)
1200            throw new OverflowException ();
1201        }
1202        return new ShortConstant (target_type, (short) Value, Location);
1203      case BuiltinTypeSpec.Type.UShort:
1204        if (in_checked_context) {
1205          if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1206            throw new OverflowException ();
1207        }
1208        return new UShortConstant (target_type, (ushort) Value, Location);
1209      case BuiltinTypeSpec.Type.UInt:
1210        if (in_checked_context) {
1211          if (Value < UInt32.MinValue)
1212            throw new OverflowException ();
1213        }
1214        return new UIntConstant (target_type, (uint) Value, Location);
1215      case BuiltinTypeSpec.Type.Long:
1216        return new LongConstant (target_type, (long) Value, Location);
1217      case BuiltinTypeSpec.Type.ULong:
1218        if (in_checked_context && Value < 0)
1219          throw new OverflowException ();
1220        return new ULongConstant (target_type, (ulong) Value, Location);
1221      case BuiltinTypeSpec.Type.Float:
1222        return new FloatConstant (target_type, (float) Value, Location);
1223      case BuiltinTypeSpec.Type.Double:
1224        return new DoubleConstant (target_type, (double) Value, Location);
1225      case BuiltinTypeSpec.Type.Char:
1226        if (in_checked_context) {
1227          if (Value < Char.MinValue || Value > Char.MaxValue)
1228            throw new OverflowException ();
1229        }
1230        return new CharConstant (target_type, (char) Value, Location);
1231      case BuiltinTypeSpec.Type.Decimal:
1232        return new DecimalConstant (target_type, (decimal) Value, Location);
1233      }
1234
1235      return null;
1236    }
1237
1238    public override Constant ConvertImplicitly (TypeSpec type)
1239    {
1240      if (this.type == type)
1241        return this;
1242
1243      Constant c = TryImplicitIntConversion (type);
1244      if (c != null)
1245        return c; //.Resolve (rc);
1246
1247      return base.ConvertImplicitly (type);
1248    }
1249
1250    /// <summary>
1251    ///   Attempts to perform an implicit constant conversion of the IntConstant
1252    ///   into a different data type using casts (See Implicit Constant
1253    ///   Expression Conversions)
1254    /// </summary>
1255    Constant TryImplicitIntConversion (TypeSpec target_type)
1256    {
1257      switch (target_type.BuiltinType) {
1258      case BuiltinTypeSpec.Type.SByte:
1259        if (Value >= SByte.MinValue && Value <= SByte.MaxValue)
1260          return new SByteConstant (target_type, (sbyte) Value, loc);
1261        break;
1262      case BuiltinTypeSpec.Type.Byte:
1263        if (Value >= Byte.MinValue && Value <= Byte.MaxValue)
1264          return new ByteConstant (target_type, (byte) Value, loc);
1265        break;
1266      case BuiltinTypeSpec.Type.Short:
1267        if (Value >= Int16.MinValue && Value <= Int16.MaxValue)
1268          return new ShortConstant (target_type, (short) Value, loc);
1269        break;
1270      case BuiltinTypeSpec.Type.UShort:
1271        if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue)
1272          return new UShortConstant (target_type, (ushort) Value, loc);
1273        break;
1274      case BuiltinTypeSpec.Type.UInt:
1275        if (Value >= 0)
1276          return new UIntConstant (target_type, (uint) Value, loc);
1277        break;
1278      case BuiltinTypeSpec.Type.ULong:
1279        //
1280        // we can optimize this case: a positive int32
1281        // always fits on a uint64.  But we need an opcode
1282        // to do it.
1283        //
1284        if (Value >= 0)
1285          return new ULongConstant (target_type, (ulong) Value, loc);
1286        break;
1287      case BuiltinTypeSpec.Type.Double:
1288        return new DoubleConstant (target_type, (double) Value, loc);
1289      case BuiltinTypeSpec.Type.Float:
1290        return new FloatConstant (target_type, (float) Value, loc);
1291      }
1292
1293      return null;
1294    }
1295  }
1296
1297  public class UIntConstant : IntegralConstant {
1298    public readonly uint Value;
1299
1300    public UIntConstant (BuiltinTypes types, uint v, Location loc)
1301      : this (types.UInt, v, loc)
1302    {
1303    }
1304
1305    public UIntConstant (TypeSpec type, uint v, Location loc)
1306      : base (type, loc)
1307    {
1308      Value = v;
1309    }
1310
1311    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1312    {
1313      enc.Encode (Value);
1314    }
1315
1316    public override void Emit (EmitContext ec)
1317    {
1318      ec.EmitInt (unchecked ((int) Value));
1319    }
1320
1321    public override object GetValue ()
1322    {
1323      return Value;
1324    }
1325
1326    public override long GetValueAsLong ()
1327    {
1328      return Value;
1329    }
1330
1331    public override Constant Increment ()
1332    {
1333      return new UIntConstant (type, checked(Value + 1), loc);
1334    }
1335 
1336    public override bool IsDefaultValue {
1337      get {
1338        return Value == 0;
1339      }
1340    }
1341
1342    public override bool IsNegative {
1343      get {
1344        return false;
1345      }
1346    }
1347   
1348    public override bool IsOneInteger {
1349      get {
1350        return Value == 1;
1351      }
1352    }   
1353
1354    public override bool IsZeroInteger {
1355      get { return Value == 0; }
1356    }
1357
1358    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1359    {
1360      switch (target_type.BuiltinType) {
1361      case BuiltinTypeSpec.Type.Byte:
1362        if (in_checked_context) {
1363          if (Value < 0 || Value > byte.MaxValue)
1364            throw new OverflowException ();
1365        }
1366        return new ByteConstant (target_type, (byte) Value, Location);
1367      case BuiltinTypeSpec.Type.SByte:
1368        if (in_checked_context) {
1369          if (Value > SByte.MaxValue)
1370            throw new OverflowException ();
1371        }
1372        return new SByteConstant (target_type, (sbyte) Value, Location);
1373      case BuiltinTypeSpec.Type.Short:
1374        if (in_checked_context) {
1375          if (Value > Int16.MaxValue)
1376            throw new OverflowException ();
1377        }
1378        return new ShortConstant (target_type, (short) Value, Location);
1379      case BuiltinTypeSpec.Type.UShort:
1380        if (in_checked_context) {
1381          if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1382            throw new OverflowException ();
1383        }
1384        return new UShortConstant (target_type, (ushort) Value, Location);
1385      case BuiltinTypeSpec.Type.Int:
1386        if (in_checked_context) {
1387          if (Value > Int32.MaxValue)
1388            throw new OverflowException ();
1389        }
1390        return new IntConstant (target_type, (int) Value, Location);
1391      case BuiltinTypeSpec.Type.Long:
1392        return new LongConstant (target_type, (long) Value, Location);
1393      case BuiltinTypeSpec.Type.ULong:
1394        return new ULongConstant (target_type, (ulong) Value, Location);
1395      case BuiltinTypeSpec.Type.Float:
1396        return new FloatConstant (target_type, (float) Value, Location);
1397      case BuiltinTypeSpec.Type.Double:
1398        return new DoubleConstant (target_type, (double) Value, Location);
1399      case BuiltinTypeSpec.Type.Char:
1400        if (in_checked_context) {
1401          if (Value < Char.MinValue || Value > Char.MaxValue)
1402            throw new OverflowException ();
1403        }
1404        return new CharConstant (target_type, (char) Value, Location);
1405      case BuiltinTypeSpec.Type.Decimal:
1406        return new DecimalConstant (target_type, (decimal) Value, Location);
1407      }
1408
1409      return null;
1410    }
1411
1412  }
1413
1414  public class LongConstant : IntegralConstant {
1415    public readonly long Value;
1416
1417    public LongConstant (BuiltinTypes types, long v, Location loc)
1418      : this (types.Long, v, loc)
1419    {
1420    }
1421
1422    public LongConstant (TypeSpec type, long v, Location loc)
1423      : base (type, loc)
1424    {
1425      Value = v;
1426    }
1427
1428    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1429    {
1430      enc.Encode (Value);
1431    }
1432
1433    public override void Emit (EmitContext ec)
1434    {
1435      ec.EmitLong (Value);
1436    }
1437
1438    public override object GetValue ()
1439    {
1440      return Value;
1441    }
1442
1443    public override long GetValueAsLong ()
1444    {
1445      return Value;
1446    }
1447
1448    public override Constant Increment ()
1449    {
1450      return new LongConstant (type, checked(Value + 1), loc);
1451    }
1452   
1453    public override bool IsDefaultValue {
1454      get {
1455        return Value == 0;
1456      }
1457    }
1458
1459    public override bool IsNegative {
1460      get {
1461        return Value < 0;
1462      }
1463    }
1464   
1465    public override bool IsOneInteger {
1466      get {
1467        return Value == 1;
1468      }
1469    }   
1470
1471    public override bool IsZeroInteger {
1472      get { return Value == 0; }
1473    }
1474
1475    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1476    {
1477      switch (target_type.BuiltinType) {
1478      case BuiltinTypeSpec.Type.Byte:
1479        if (in_checked_context) {
1480          if (Value < Byte.MinValue || Value > Byte.MaxValue)
1481            throw new OverflowException ();
1482        }
1483        return new ByteConstant (target_type, (byte) Value, Location);
1484      case BuiltinTypeSpec.Type.SByte:
1485        if (in_checked_context) {
1486          if (Value < SByte.MinValue || Value > SByte.MaxValue)
1487            throw new OverflowException ();
1488        }
1489        return new SByteConstant (target_type, (sbyte) Value, Location);
1490      case BuiltinTypeSpec.Type.Short:
1491        if (in_checked_context) {
1492          if (Value < Int16.MinValue || Value > Int16.MaxValue)
1493            throw new OverflowException ();
1494        }
1495        return new ShortConstant (target_type, (short) Value, Location);
1496      case BuiltinTypeSpec.Type.UShort:
1497        if (in_checked_context) {
1498          if (Value < UInt16.MinValue || Value > UInt16.MaxValue)
1499            throw new OverflowException ();
1500        }
1501        return new UShortConstant (target_type, (ushort) Value, Location);
1502      case BuiltinTypeSpec.Type.Int:
1503        if (in_checked_context) {
1504          if (Value < Int32.MinValue || Value > Int32.MaxValue)
1505            throw new OverflowException ();
1506        }
1507        return new IntConstant (target_type, (int) Value, Location);
1508      case BuiltinTypeSpec.Type.UInt:
1509        if (in_checked_context) {
1510          if (Value < UInt32.MinValue || Value > UInt32.MaxValue)
1511            throw new OverflowException ();
1512        }
1513        return new UIntConstant (target_type, (uint) Value, Location);
1514      case BuiltinTypeSpec.Type.ULong:
1515        if (in_checked_context && Value < 0)
1516          throw new OverflowException ();
1517        return new ULongConstant (target_type, (ulong) Value, Location);
1518      case BuiltinTypeSpec.Type.Float:
1519        return new FloatConstant (target_type, (float) Value, Location);
1520      case BuiltinTypeSpec.Type.Double:
1521        return new DoubleConstant (target_type, (double) Value, Location);
1522      case BuiltinTypeSpec.Type.Char:
1523        if (in_checked_context) {
1524          if (Value < Char.MinValue || Value > Char.MaxValue)
1525            throw new OverflowException ();
1526        }
1527        return new CharConstant (target_type, (char) Value, Location);
1528      case BuiltinTypeSpec.Type.Decimal:
1529        return new DecimalConstant (target_type, (decimal) Value, Location);
1530      }
1531
1532      return null;
1533    }
1534
1535    public override Constant ConvertImplicitly (TypeSpec type)
1536    {
1537      if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) {
1538        return new ULongConstant (type, (ulong) Value, loc);
1539      }
1540
1541      return base.ConvertImplicitly (type);
1542    }
1543  }
1544
1545  public class ULongConstant : IntegralConstant {
1546    public readonly ulong Value;
1547
1548    public ULongConstant (BuiltinTypes types, ulong v, Location loc)
1549      : this (types.ULong, v, loc)
1550    {
1551    }
1552
1553    public ULongConstant (TypeSpec type, ulong v, Location loc)
1554      : base (type, loc)
1555    {
1556      Value = v;
1557    }
1558
1559    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1560    {
1561      enc.Encode (Value);
1562    }
1563
1564    public override void Emit (EmitContext ec)
1565    {
1566      ec.EmitLong (unchecked ((long) Value));
1567    }
1568
1569    public override object GetValue ()
1570    {
1571      return Value;
1572    }
1573
1574    public override long GetValueAsLong ()
1575    {
1576      return (long) Value;
1577    }
1578
1579    public override Constant Increment ()
1580    {
1581      return new ULongConstant (type, checked(Value + 1), loc);
1582    }
1583
1584    public override bool IsDefaultValue {
1585      get {
1586        return Value == 0;
1587      }
1588    }
1589
1590    public override bool IsNegative {
1591      get {
1592        return false;
1593      }
1594    }
1595   
1596    public override bool IsOneInteger {
1597      get {
1598        return Value == 1;
1599      }
1600    }   
1601
1602    public override bool IsZeroInteger {
1603      get { return Value == 0; }
1604    }
1605
1606    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1607    {
1608      switch (target_type.BuiltinType) {
1609      case BuiltinTypeSpec.Type.Byte:
1610        if (in_checked_context && Value > Byte.MaxValue)
1611          throw new OverflowException ();
1612        return new ByteConstant (target_type, (byte) Value, Location);
1613      case BuiltinTypeSpec.Type.SByte:
1614        if (in_checked_context && Value > ((ulong) SByte.MaxValue))
1615          throw new OverflowException ();
1616        return new SByteConstant (target_type, (sbyte) Value, Location);
1617      case BuiltinTypeSpec.Type.Short:
1618        if (in_checked_context && Value > ((ulong) Int16.MaxValue))
1619          throw new OverflowException ();
1620        return new ShortConstant (target_type, (short) Value, Location);
1621      case BuiltinTypeSpec.Type.UShort:
1622        if (in_checked_context && Value > UInt16.MaxValue)
1623          throw new OverflowException ();
1624        return new UShortConstant (target_type, (ushort) Value, Location);
1625      case BuiltinTypeSpec.Type.Int:
1626        if (in_checked_context && Value > UInt32.MaxValue)
1627          throw new OverflowException ();
1628        return new IntConstant (target_type, (int) Value, Location);
1629      case BuiltinTypeSpec.Type.UInt:
1630        if (in_checked_context && Value > UInt32.MaxValue)
1631          throw new OverflowException ();
1632        return new UIntConstant (target_type, (uint) Value, Location);
1633      case BuiltinTypeSpec.Type.Long:
1634        if (in_checked_context && Value > Int64.MaxValue)
1635          throw new OverflowException ();
1636        return new LongConstant (target_type, (long) Value, Location);
1637      case BuiltinTypeSpec.Type.Float:
1638        return new FloatConstant (target_type, (float) Value, Location);
1639      case BuiltinTypeSpec.Type.Double:
1640        return new DoubleConstant (target_type, (double) Value, Location);
1641      case BuiltinTypeSpec.Type.Char:
1642        if (in_checked_context && Value > Char.MaxValue)
1643          throw new OverflowException ();
1644        return new CharConstant (target_type, (char) Value, Location);
1645      case BuiltinTypeSpec.Type.Decimal:
1646        return new DecimalConstant (target_type, (decimal) Value, Location);
1647      }
1648
1649      return null;
1650    }
1651
1652  }
1653
1654  public class FloatConstant : Constant {
1655    //
1656    // Store constant value as double because float constant operations
1657    // need to work on double value to match JIT
1658    //
1659    public readonly double DoubleValue;
1660
1661    public FloatConstant (BuiltinTypes types, double v, Location loc)
1662      : this (types.Float, v, loc)
1663    {
1664    }
1665
1666    public FloatConstant (TypeSpec type, double v, Location loc)
1667      : base (loc)
1668    {
1669      this.type = type;
1670      eclass = ExprClass.Value;
1671
1672      DoubleValue = v;
1673    }
1674
1675    public override Constant ConvertImplicitly (TypeSpec type)
1676    {
1677      if (type.BuiltinType == BuiltinTypeSpec.Type.Double)
1678        return new DoubleConstant (type, DoubleValue, loc);
1679
1680      return base.ConvertImplicitly (type);
1681    }
1682
1683    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1684    {
1685      enc.Encode (Value);
1686    }
1687
1688    public override void Emit (EmitContext ec)
1689    {
1690      ec.Emit (OpCodes.Ldc_R4, Value);
1691    }
1692
1693    public float Value {
1694      get {
1695        return (float) DoubleValue;
1696      }
1697    }
1698
1699    public override object GetValue ()
1700    {
1701      return Value;
1702    }
1703
1704    public override string GetValueAsLiteral ()
1705    {
1706      return Value.ToString ();
1707    }
1708
1709    public override long GetValueAsLong ()
1710    {
1711      throw new NotSupportedException ();
1712    }
1713
1714    public override bool IsDefaultValue {
1715      get {
1716        return Value == 0;
1717      }
1718    }
1719
1720    public override bool IsNegative {
1721      get {
1722        return Value < 0;
1723      }
1724    }
1725
1726    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1727    {
1728      switch (target_type.BuiltinType) {
1729      case BuiltinTypeSpec.Type.Byte:
1730        if (in_checked_context) {
1731          if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value))
1732            throw new OverflowException ();
1733        }
1734        return new ByteConstant (target_type, (byte) DoubleValue, Location);
1735      case BuiltinTypeSpec.Type.SByte:
1736        if (in_checked_context) {
1737          if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value))
1738            throw new OverflowException ();
1739        }
1740        return new SByteConstant (target_type, (sbyte) DoubleValue, Location);
1741      case BuiltinTypeSpec.Type.Short:
1742        if (in_checked_context) {
1743          if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value))
1744            throw new OverflowException ();
1745        }
1746        return new ShortConstant (target_type, (short) DoubleValue, Location);
1747      case BuiltinTypeSpec.Type.UShort:
1748        if (in_checked_context) {
1749          if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value))
1750            throw new OverflowException ();
1751        }
1752        return new UShortConstant (target_type, (ushort) DoubleValue, Location);
1753      case BuiltinTypeSpec.Type.Int:
1754        if (in_checked_context) {
1755          if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value))
1756            throw new OverflowException ();
1757        }
1758        return new IntConstant (target_type, (int) DoubleValue, Location);
1759      case BuiltinTypeSpec.Type.UInt:
1760        if (in_checked_context) {
1761          if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value))
1762            throw new OverflowException ();
1763        }
1764        return new UIntConstant (target_type, (uint) DoubleValue, Location);
1765      case BuiltinTypeSpec.Type.Long:
1766        if (in_checked_context) {
1767          if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value))
1768            throw new OverflowException ();
1769        }
1770        return new LongConstant (target_type, (long) DoubleValue, Location);
1771      case BuiltinTypeSpec.Type.ULong:
1772        if (in_checked_context) {
1773          if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value))
1774            throw new OverflowException ();
1775        }
1776        return new ULongConstant (target_type, (ulong) DoubleValue, Location);
1777      case BuiltinTypeSpec.Type.Double:
1778        return new DoubleConstant (target_type, DoubleValue, Location);
1779      case BuiltinTypeSpec.Type.Char:
1780        if (in_checked_context) {
1781          if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value))
1782            throw new OverflowException ();
1783        }
1784        return new CharConstant (target_type, (char) DoubleValue, Location);
1785      case BuiltinTypeSpec.Type.Decimal:
1786        return new DecimalConstant (target_type, (decimal) DoubleValue, Location);
1787      }
1788
1789      return null;
1790    }
1791
1792  }
1793
1794  public class DoubleConstant : Constant
1795  {
1796    public readonly double Value;
1797
1798    public DoubleConstant (BuiltinTypes types, double v, Location loc)
1799      : this (types.Double, v, loc)
1800    {
1801    }
1802
1803    public DoubleConstant (TypeSpec type, double v, Location loc)
1804      : base (loc)
1805    {
1806      this.type = type;
1807      eclass = ExprClass.Value;
1808
1809      Value = v;
1810    }
1811
1812    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1813    {
1814      enc.Encode (Value);
1815    }
1816
1817    public override void Emit (EmitContext ec)
1818    {
1819      ec.Emit (OpCodes.Ldc_R8, Value);
1820    }
1821
1822    public override object GetValue ()
1823    {
1824      return Value;
1825    }
1826
1827    public override string GetValueAsLiteral ()
1828    {
1829      return Value.ToString ();
1830    }
1831
1832    public override long GetValueAsLong ()
1833    {
1834      throw new NotSupportedException ();
1835    }
1836
1837    public override bool IsDefaultValue {
1838      get {
1839        return Value == 0;
1840      }
1841    }
1842
1843    public override bool IsNegative {
1844      get {
1845        return Value < 0;
1846      }
1847    }
1848
1849    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1850    {
1851      switch (target_type.BuiltinType) {
1852      case BuiltinTypeSpec.Type.Byte:
1853        if (in_checked_context) {
1854          if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value))
1855            throw new OverflowException ();
1856        }
1857        return new ByteConstant (target_type, (byte) Value, Location);
1858      case BuiltinTypeSpec.Type.SByte:
1859        if (in_checked_context) {
1860          if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value))
1861            throw new OverflowException ();
1862        }
1863        return new SByteConstant (target_type, (sbyte) Value, Location);
1864      case BuiltinTypeSpec.Type.Short:
1865        if (in_checked_context) {
1866          if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value))
1867            throw new OverflowException ();
1868        }
1869        return new ShortConstant (target_type, (short) Value, Location);
1870      case BuiltinTypeSpec.Type.UShort:
1871        if (in_checked_context) {
1872          if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value))
1873            throw new OverflowException ();
1874        }
1875        return new UShortConstant (target_type, (ushort) Value, Location);
1876      case BuiltinTypeSpec.Type.Int:
1877        if (in_checked_context) {
1878          if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value))
1879            throw new OverflowException ();
1880        }
1881        return new IntConstant (target_type, (int) Value, Location);
1882      case BuiltinTypeSpec.Type.UInt:
1883        if (in_checked_context) {
1884          if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value))
1885            throw new OverflowException ();
1886        }
1887        return new UIntConstant (target_type, (uint) Value, Location);
1888      case BuiltinTypeSpec.Type.Long:
1889        if (in_checked_context) {
1890          if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value))
1891            throw new OverflowException ();
1892        }
1893        return new LongConstant (target_type, (long) Value, Location);
1894      case BuiltinTypeSpec.Type.ULong:
1895        if (in_checked_context) {
1896          if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value))
1897            throw new OverflowException ();
1898        }
1899        return new ULongConstant (target_type, (ulong) Value, Location);
1900      case BuiltinTypeSpec.Type.Float:
1901        return new FloatConstant (target_type, (float) Value, Location);
1902      case BuiltinTypeSpec.Type.Char:
1903        if (in_checked_context) {
1904          if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value))
1905            throw new OverflowException ();
1906        }
1907        return new CharConstant (target_type, (char) Value, Location);
1908      case BuiltinTypeSpec.Type.Decimal:
1909        return new DecimalConstant (target_type, (decimal) Value, Location);
1910      }
1911
1912      return null;
1913    }
1914
1915  }
1916
1917  public class DecimalConstant : Constant {
1918    public readonly decimal Value;
1919
1920    public DecimalConstant (BuiltinTypes types, decimal d, Location loc)
1921      : this (types.Decimal, d, loc)
1922    {
1923    }
1924
1925    public DecimalConstant (TypeSpec type, decimal d, Location loc)
1926      : base (loc)
1927    {
1928      this.type = type;
1929      eclass = ExprClass.Value;
1930
1931      Value = d;
1932    }
1933
1934    public override void Emit (EmitContext ec)
1935    {
1936      MethodSpec m;
1937
1938      int [] words = decimal.GetBits (Value);
1939      int power = (words [3] >> 16) & 0xff;
1940
1941      if (power == 0) {
1942        if (Value <= int.MaxValue && Value >= int.MinValue) {
1943          m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc);
1944          if (m == null) {
1945            return;
1946          }
1947
1948          ec.EmitInt ((int) Value);
1949          ec.Emit (OpCodes.Newobj, m);
1950          return;
1951        }
1952
1953        if (Value <= long.MaxValue && Value >= long.MinValue) {
1954          m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc);
1955          if (m == null) {
1956            return;
1957          }
1958
1959          ec.EmitLong ((long) Value);
1960          ec.Emit (OpCodes.Newobj, m);
1961          return;
1962        }
1963      }
1964
1965      ec.EmitInt (words [0]);
1966      ec.EmitInt (words [1]);
1967      ec.EmitInt (words [2]);
1968
1969      // sign
1970      ec.EmitInt (words [3] >> 31);
1971
1972      // power
1973      ec.EmitInt (power);
1974
1975      m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc);
1976      if (m != null) {
1977        ec.Emit (OpCodes.Newobj, m);
1978      }
1979    }
1980
1981    public override bool IsDefaultValue {
1982      get {
1983        return Value == 0;
1984      }
1985    }
1986
1987    public override bool IsNegative {
1988      get {
1989        return Value < 0;
1990      }
1991    }
1992
1993    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1994    {
1995      switch (target_type.BuiltinType) {
1996      case BuiltinTypeSpec.Type.SByte:
1997        return new SByteConstant (target_type, (sbyte) Value, loc);
1998      case BuiltinTypeSpec.Type.Byte:
1999        return new ByteConstant (target_type, (byte) Value, loc);
2000      case BuiltinTypeSpec.Type.Short:
2001        return new ShortConstant (target_type, (short) Value, loc);
2002      case BuiltinTypeSpec.Type.UShort:
2003        return new UShortConstant (target_type, (ushort) Value, loc);
2004      case BuiltinTypeSpec.Type.Int:
2005        return new IntConstant (target_type, (int) Value, loc);
2006      case BuiltinTypeSpec.Type.UInt:
2007        return new UIntConstant (target_type, (uint) Value, loc);
2008      case BuiltinTypeSpec.Type.Long:
2009        return new LongConstant (target_type, (long) Value, loc);
2010      case BuiltinTypeSpec.Type.ULong:
2011        return new ULongConstant (target_type, (ulong) Value, loc);
2012      case BuiltinTypeSpec.Type.Char:
2013        return new CharConstant (target_type, (char) Value, loc);
2014      case BuiltinTypeSpec.Type.Float:
2015        return new FloatConstant (target_type, (float) Value, loc);
2016      case BuiltinTypeSpec.Type.Double:
2017        return new DoubleConstant (target_type, (double) Value, loc);
2018      }
2019
2020      return null;
2021    }
2022
2023    public override object GetValue ()
2024    {
2025      return Value;
2026    }
2027
2028    public override string GetValueAsLiteral ()
2029    {
2030      return Value.ToString () + "M";
2031    }
2032
2033    public override long GetValueAsLong ()
2034    {
2035      throw new NotSupportedException ();
2036    }
2037  }
2038
2039  public class StringConstant : Constant {
2040    public StringConstant (BuiltinTypes types, string s, Location loc)
2041      : this (types.String, s, loc)
2042    {
2043    }
2044
2045    public StringConstant (TypeSpec type, string s, Location loc)
2046      : base (loc)
2047    {
2048      this.type = type;
2049      eclass = ExprClass.Value;
2050
2051      Value = s;
2052    }
2053
2054    protected StringConstant (Location loc)
2055      : base (loc)
2056    {
2057    }
2058
2059    public string Value { get; protected set; }
2060
2061    public override object GetValue ()
2062    {
2063      return Value;
2064    }
2065
2066    public override string GetValueAsLiteral ()
2067    {
2068      // FIXME: Escape the string.
2069      return "\"" + Value + "\"";
2070    }
2071
2072    public override long GetValueAsLong ()
2073    {
2074      throw new NotSupportedException ();
2075    }
2076   
2077    public override void Emit (EmitContext ec)
2078    {
2079      if (Value == null) {
2080        ec.EmitNull ();
2081        return;
2082      }
2083
2084      //
2085      // Use string.Empty for both literals and constants even if
2086      // it's not allowed at language level
2087      //
2088      if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) {
2089        var string_type = ec.BuiltinTypes.String;
2090        if (ec.CurrentType != string_type) {
2091          var m = ec.Module.PredefinedMembers.StringEmpty.Get ();
2092          if (m != null) {
2093            ec.Emit (OpCodes.Ldsfld, m);
2094            return;
2095          }
2096        }
2097      }
2098
2099      ec.Emit (OpCodes.Ldstr, Value);
2100    }
2101
2102    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
2103    {
2104      // cast to object
2105      if (type != targetType)
2106        enc.Encode (type);
2107
2108      enc.Encode (Value);
2109    }
2110
2111    public override bool IsDefaultValue {
2112      get {
2113        return Value == null;
2114      }
2115    }
2116
2117    public override bool IsNegative {
2118      get {
2119        return false;
2120      }
2121    }
2122
2123    public override bool IsNull {
2124      get {
2125        return IsDefaultValue;
2126      }
2127    }
2128
2129    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2130    {
2131      return null;
2132    }
2133
2134    public override Constant ConvertImplicitly (TypeSpec type)
2135    {
2136      if (IsDefaultValue && type.BuiltinType == BuiltinTypeSpec.Type.Object)
2137        return new NullConstant (type, loc);
2138
2139      return base.ConvertImplicitly (type);
2140    }
2141  }
2142
2143  class NameOf : StringConstant
2144  {
2145    readonly SimpleName name;
2146
2147    public NameOf (SimpleName name)
2148      : base (name.Location)
2149    {
2150      this.name = name;
2151    }
2152
2153    protected override Expression DoResolve (ResolveContext rc)
2154    {
2155      throw new NotSupportedException ();
2156    }
2157
2158    bool ResolveArgumentExpression (ResolveContext rc, Expression expr)
2159    {
2160      var sn = expr as SimpleName;
2161      if (sn != null) {
2162        Value = sn.Name;
2163
2164        if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6)
2165          rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
2166
2167        if (sn.HasTypeArguments) {
2168          // TODO: csc compatible but unhelpful error message
2169          rc.Report.Error (1001, loc, "Identifier expected");
2170          return true;
2171        }
2172
2173        sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreArity | MemberLookupRestrictions.IgnoreAmbiguity);
2174        return true;
2175      }
2176
2177      var ma = expr as MemberAccess;
2178      if (ma != null) {
2179        FullNamedExpression fne = ma.LeftExpression as ATypeNameExpression;
2180        if (fne == null) {
2181          var qam = ma as QualifiedAliasMember;
2182          if (qam == null)
2183            return false;
2184
2185          fne = qam.CreateExpressionFromAlias (rc);
2186          if (fne == null)
2187            return true;
2188        }
2189
2190        Value = ma.Name;
2191
2192        if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6)
2193          rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
2194
2195        if (ma.HasTypeArguments) {
2196          // TODO: csc compatible but unhelpful error message
2197          rc.Report.Error (1001, loc, "Identifier expected");
2198          return true;
2199        }
2200         
2201        var left = fne.ResolveAsTypeOrNamespace (rc, true);
2202        if (left == null)
2203          return true;
2204
2205        var ns = left as NamespaceExpression;
2206        if (ns != null) {
2207          FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, ma.Name, 0, LookupMode.NameOf, loc);
2208          if (retval == null)
2209            ns.Error_NamespaceDoesNotExist (rc, ma.Name, 0);
2210
2211          return true;
2212        }
2213
2214        if (left.Type.IsGenericOrParentIsGeneric && left.Type.GetDefinition () != left.Type) {
2215          rc.Report.Error (8071, loc, "Type arguments are not allowed in the nameof operator");
2216        }
2217
2218        var mexpr = MemberLookup (rc, false, left.Type, ma.Name, 0, MemberLookupRestrictions.IgnoreArity | MemberLookupRestrictions.IgnoreAmbiguity, loc);
2219        if (mexpr == null) {
2220          ma.Error_IdentifierNotFound (rc, left.Type);
2221          return true;
2222        }
2223
2224        return true;
2225      }
2226
2227      return false;
2228    }
2229
2230    public Expression ResolveOverload (ResolveContext rc, Arguments args)
2231    {
2232      if (args == null || args.Count != 1) {
2233        name.Error_NameDoesNotExist (rc);
2234        return null;
2235      }
2236
2237      var arg = args [0];
2238      var res = ResolveArgumentExpression (rc, arg.Expr);
2239      if (!res) {
2240        name.Error_NameDoesNotExist (rc);
2241        return null;
2242      }
2243
2244      type = rc.BuiltinTypes.String;
2245      eclass = ExprClass.Value;
2246      return this;
2247    }
2248  }
2249
2250  //
2251  // Null constant can have its own type, think of `default (Foo)'
2252  //
2253  public class NullConstant : Constant
2254  {
2255    public NullConstant (TypeSpec type, Location loc)
2256      : base (loc)
2257    {
2258      eclass = ExprClass.Value;
2259      this.type = type;
2260    }
2261
2262    public override Expression CreateExpressionTree (ResolveContext ec)
2263    {
2264      if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2265        // Optimized version, also avoids referencing literal internal type
2266        Arguments args = new Arguments (1);
2267        args.Add (new Argument (this));
2268        return CreateExpressionFactoryCall (ec, "Constant", args);
2269      }
2270
2271      return base.CreateExpressionTree (ec);
2272    }
2273
2274    public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
2275    {
2276      switch (targetType.BuiltinType) {
2277      case BuiltinTypeSpec.Type.Object:
2278        // Type it as string cast
2279        enc.Encode (rc.Module.Compiler.BuiltinTypes.String);
2280        goto case BuiltinTypeSpec.Type.String;
2281      case BuiltinTypeSpec.Type.String:
2282      case BuiltinTypeSpec.Type.Type:
2283        enc.Encode (byte.MaxValue);
2284        return;
2285      default:
2286        var ac = targetType as ArrayContainer;
2287        if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) {
2288          enc.Encode (uint.MaxValue);
2289          return;
2290        }
2291
2292        break;
2293      }
2294
2295      base.EncodeAttributeValue (rc, enc, targetType, parameterType);
2296    }
2297
2298    public override void Emit (EmitContext ec)
2299    {
2300      ec.EmitNull ();
2301
2302      // Only to make verifier happy
2303      if (type.IsGenericParameter)
2304        ec.Emit (OpCodes.Unbox_Any, type);
2305    }
2306
2307    public override string ExprClassName {
2308      get {
2309        return GetSignatureForError ();
2310      }
2311    }
2312
2313    public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
2314    {
2315      if (targetType.IsPointer) {
2316        if (IsLiteral || this is NullPointer)
2317          return new NullPointer (targetType, loc);
2318
2319        return null;
2320      }
2321
2322      // Exlude internal compiler types
2323      if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic)
2324        return null;
2325
2326      if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
2327        return null;
2328
2329      if (TypeSpec.IsReferenceType (targetType))
2330        return new NullConstant (targetType, loc);
2331
2332      if (targetType.IsNullableType)
2333        return Nullable.LiftedNull.Create (targetType, loc);
2334
2335      return null;
2336    }
2337
2338    public override Constant ConvertImplicitly (TypeSpec targetType)
2339    {
2340      return ConvertExplicitly (false, targetType);
2341    }
2342
2343    public override string GetSignatureForError ()
2344    {
2345      return "null";
2346    }
2347
2348    public override object GetValue ()
2349    {
2350      return null;
2351    }
2352
2353    public override string GetValueAsLiteral ()
2354    {
2355      return GetSignatureForError ();
2356    }
2357
2358    public override long GetValueAsLong ()
2359    {
2360      throw new NotSupportedException ();
2361    }
2362
2363    public override bool IsDefaultValue {
2364      get { return true; }
2365    }
2366
2367    public override bool IsNegative {
2368      get { return false; }
2369    }
2370
2371    public override bool IsNull {
2372      get { return true; }
2373    }
2374
2375    public override bool IsZeroInteger {
2376      get { return true; }
2377    }
2378  }
2379
2380
2381  //
2382  // A null constant in a pointer context
2383  //
2384  class NullPointer : NullConstant
2385  {
2386    public NullPointer (TypeSpec type, Location loc)
2387      : base (type, loc)
2388    {
2389    }
2390
2391    public override Expression CreateExpressionTree (ResolveContext ec)
2392    {
2393      Error_PointerInsideExpressionTree (ec);
2394      return base.CreateExpressionTree (ec);
2395    }
2396
2397    public override void Emit (EmitContext ec)
2398    {
2399      //
2400      // Emits null pointer
2401      //
2402      ec.EmitInt (0);
2403      ec.Emit (OpCodes.Conv_U);
2404    }
2405  }
2406
2407  /// <summary>
2408  ///   The value is constant, but when emitted has a side effect.  This is
2409  ///   used by BitwiseAnd to ensure that the second expression is invoked
2410  ///   regardless of the value of the left side. 
2411  /// </summary>
2412  public class SideEffectConstant : Constant
2413  {
2414    public readonly Constant value;
2415    Expression side_effect;
2416   
2417    public SideEffectConstant (Constant value, Expression side_effect, Location loc)
2418      : base (loc)
2419    {
2420      this.value = value;
2421      type = value.Type;
2422      eclass = ExprClass.Value;
2423
2424      while (side_effect is SideEffectConstant)
2425        side_effect = ((SideEffectConstant) side_effect).side_effect;
2426      this.side_effect = side_effect;
2427    }
2428
2429    public override bool IsSideEffectFree {
2430      get {
2431        return false;
2432      }
2433    }
2434
2435    public override bool ContainsEmitWithAwait ()
2436    {
2437      return side_effect.ContainsEmitWithAwait ();
2438    }
2439
2440    public override object GetValue ()
2441    {
2442      return value.GetValue ();
2443    }
2444
2445    public override string GetValueAsLiteral ()
2446    {
2447      return value.GetValueAsLiteral ();
2448    }
2449
2450    public override long GetValueAsLong ()
2451    {
2452      return value.GetValueAsLong ();
2453    }
2454
2455    public override void Emit (EmitContext ec)
2456    {
2457      side_effect.EmitSideEffect (ec);
2458      value.Emit (ec);
2459    }
2460
2461    public override void EmitSideEffect (EmitContext ec)
2462    {
2463      side_effect.EmitSideEffect (ec);
2464      value.EmitSideEffect (ec);
2465    }
2466
2467    public override void FlowAnalysis (FlowAnalysisContext fc)
2468    {
2469      side_effect.FlowAnalysis (fc);
2470    }
2471
2472    public override bool IsDefaultValue {
2473      get { return value.IsDefaultValue; }
2474    }
2475
2476    public override bool IsNegative {
2477      get { return value.IsNegative; }
2478    }
2479
2480    public override bool IsZeroInteger {
2481      get { return value.IsZeroInteger; }
2482    }
2483
2484    public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2485    {
2486      Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
2487      if (new_value == null)
2488        return null;
2489
2490      var c = new SideEffectConstant (new_value, side_effect, new_value.Location);
2491      c.type = target_type;
2492      c.eclass = eclass;
2493      return c;
2494    }
2495  }
2496}
Note: See TracBrowser for help on using the repository browser.