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 
Constant(Location loc)31 		protected Constant (Location loc)
32 		{
33 			this.loc = loc;
34 		}
35 
ToString()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>
GetValue()45 		public abstract object GetValue ();
46 
GetValueAsLong()47 		public abstract long GetValueAsLong ();
48 
GetValueAsLiteral()49 		public abstract string GetValueAsLiteral ();
50 
51 #if !STATIC
52 		//
53 		// Returns an object value which is typed to contant type
54 		//
GetTypedValue()55 		public virtual object GetTypedValue ()
56 		{
57 			return GetValue ();
58 		}
59 #endif
60 
Error_ValueCannotBeConverted(ResolveContext ec, TypeSpec target, bool expl)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 
ImplicitConversionRequired(ResolveContext ec, TypeSpec type)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 
ContainsEmitWithAwait()82 		public override bool ContainsEmitWithAwait ()
83 		{
84 			return false;
85 		}
86 
ConvertImplicitly(TypeSpec type)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 		//
CreateConstantFromValue(TypeSpec t, object v, Location loc)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 		//
ExtractConstantFromValue(TypeSpec t, object v, Location loc)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 
CreateExpressionTree(ResolveContext ec)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
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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.
ChangeType(object value, TypeSpec targetType, out bool error)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 
DoResolve(ResolveContext rc)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 		//
Reduce(ResolveContext ec, TypeSpec target_type)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 
TryReduce(ResolveContext rc, TypeSpec targetType)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 
TryReduceConstant(ResolveContext ec, TypeSpec target_type)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>
IsDefaultInitializer(TypeSpec type)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 
EmitSideEffect(EmitContext ec)431 		public override void EmitSideEffect (EmitContext ec)
432 		{
433 			// do nothing
434 		}
435 
Clone(CloneContext clonectx)436 		public sealed override Expression Clone (CloneContext clonectx)
437 		{
438 			// No cloning is not needed for constants
439 			return this;
440 		}
441 
CloneTo(CloneContext clonectx, Expression target)442 		protected override void CloneTo (CloneContext clonectx, Expression target)
443 		{
444 			throw new NotSupportedException ("should not be reached");
445 		}
446 
MakeExpression(BuilderContext ctx)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 
Resolve(ResolveContext rc)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 	{
IntegralConstant(TypeSpec type, Location loc)465 		protected IntegralConstant (TypeSpec type, Location loc)
466 			: base (loc)
467 		{
468 			this.type = type;
469 			eclass = ExprClass.Value;
470 		}
471 
Error_ValueCannotBeConverted(ResolveContext ec, TypeSpec target, bool expl)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 
GetValueAsLiteral()485 		public override string GetValueAsLiteral ()
486 		{
487 			return GetValue ().ToString ();
488 		}
489 
Increment()490 		public abstract Constant Increment ();
491 	}
492 
493 	public class BoolConstant : Constant {
494 		public readonly bool Value;
495 
BoolConstant(BuiltinTypes types, bool val, Location loc)496 		public BoolConstant (BuiltinTypes types, bool val, Location loc)
497 			: this (types.Bool, val, loc)
498 		{
499 		}
500 
BoolConstant(TypeSpec type, bool val, Location loc)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 
GetValue()510 		public override object GetValue ()
511 		{
512 			return (object) Value;
513 		}
514 
GetValueAsLiteral()515 		public override string GetValueAsLiteral ()
516 		{
517 			return Value ? "true" : "false";
518 		}
519 
GetValueAsLong()520 		public override long GetValueAsLong ()
521 		{
522 			return Value ? 1 : 0;
523 		}
524 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)525 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
526 		{
527 			enc.Encode (Value);
528 		}
529 
Emit(EmitContext ec)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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
ByteConstant(BuiltinTypes types, byte v, Location loc)565 		public ByteConstant (BuiltinTypes types, byte v, Location loc)
566 			: this (types.Byte, v, loc)
567 		{
568 		}
569 
ByteConstant(TypeSpec type, byte v, Location loc)570 		public ByteConstant (TypeSpec type, byte v, Location loc)
571 			: base (type, loc)
572 		{
573 			Value = v;
574 		}
575 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)576 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
577 		{
578 			enc.Encode (Value);
579 		}
580 
Emit(EmitContext ec)581 		public override void Emit (EmitContext ec)
582 		{
583 			ec.EmitInt (Value);
584 		}
585 
GetValue()586 		public override object GetValue ()
587 		{
588 			return Value;
589 		}
590 
GetValueAsLong()591 		public override long GetValueAsLong ()
592 		{
593 			return Value;
594 		}
595 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
CharConstant(BuiltinTypes types, char v, Location loc)662 		public CharConstant (BuiltinTypes types, char v, Location loc)
663 			: this (types.Char, v, loc)
664 		{
665 		}
666 
CharConstant(TypeSpec type, char v, Location loc)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 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)676 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
677 		{
678 			enc.Encode ((ushort) Value);
679 		}
680 
Emit(EmitContext ec)681 		public override void Emit (EmitContext ec)
682 		{
683 			ec.EmitInt (Value);
684 		}
685 
descape(char c)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 
GetValue()715 		public override object GetValue ()
716 		{
717 			return Value;
718 		}
719 
GetValueAsLong()720 		public override long GetValueAsLong ()
721 		{
722 			return Value;
723 		}
724 
GetValueAsLiteral()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
SByteConstant(BuiltinTypes types, sbyte v, Location loc)793 		public SByteConstant (BuiltinTypes types, sbyte v, Location loc)
794 			: this (types.SByte, v, loc)
795 		{
796 		}
797 
SByteConstant(TypeSpec type, sbyte v, Location loc)798 		public SByteConstant (TypeSpec type, sbyte v, Location loc)
799 			: base (type, loc)
800 		{
801 			Value = v;
802 		}
803 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)804 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
805 		{
806 			enc.Encode (Value);
807 		}
808 
Emit(EmitContext ec)809 		public override void Emit (EmitContext ec)
810 		{
811 			ec.EmitInt (Value);
812 		}
813 
GetValue()814 		public override object GetValue ()
815 		{
816 			return Value;
817 		}
818 
GetValueAsLong()819 		public override long GetValueAsLong ()
820 		{
821 			return Value;
822 		}
823 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
ShortConstant(BuiltinTypes types, short v, Location loc)896 		public ShortConstant (BuiltinTypes types, short v, Location loc)
897 			: this (types.Short, v, loc)
898 		{
899 		}
900 
ShortConstant(TypeSpec type, short v, Location loc)901 		public ShortConstant (TypeSpec type, short v, Location loc)
902 			: base (type, loc)
903 		{
904 			Value = v;
905 		}
906 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)907 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
908 		{
909 			enc.Encode (Value);
910 		}
911 
Emit(EmitContext ec)912 		public override void Emit (EmitContext ec)
913 		{
914 			ec.EmitInt (Value);
915 		}
916 
GetValue()917 		public override object GetValue ()
918 		{
919 			return Value;
920 		}
921 
GetValueAsLong()922 		public override long GetValueAsLong ()
923 		{
924 			return Value;
925 		}
926 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
UShortConstant(BuiltinTypes types, ushort v, Location loc)1009 		public UShortConstant (BuiltinTypes types, ushort v, Location loc)
1010 			: this (types.UShort, v, loc)
1011 		{
1012 		}
1013 
UShortConstant(TypeSpec type, ushort v, Location loc)1014 		public UShortConstant (TypeSpec type, ushort v, Location loc)
1015 			: base (type, loc)
1016 		{
1017 			Value = v;
1018 		}
1019 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1020 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1021 		{
1022 			enc.Encode (Value);
1023 		}
1024 
Emit(EmitContext ec)1025 		public override void Emit (EmitContext ec)
1026 		{
1027 			ec.EmitInt (Value);
1028 		}
1029 
GetValue()1030 		public override object GetValue ()
1031 		{
1032 			return Value;
1033 		}
1034 
GetValueAsLong()1035 		public override long GetValueAsLong ()
1036 		{
1037 			return Value;
1038 		}
1039 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
IntConstant(BuiltinTypes types, int v, Location loc)1118 		public IntConstant (BuiltinTypes types, int v, Location loc)
1119 			: this (types.Int, v, loc)
1120 		{
1121 		}
1122 
IntConstant(TypeSpec type, int v, Location loc)1123 		public IntConstant (TypeSpec type, int v, Location loc)
1124 			: base (type, loc)
1125 		{
1126 			Value = v;
1127 		}
1128 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1129 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1130 		{
1131 			enc.Encode (Value);
1132 		}
1133 
Emit(EmitContext ec)1134 		public override void Emit (EmitContext ec)
1135 		{
1136 			ec.EmitInt (Value);
1137 		}
1138 
GetValue()1139 		public override object GetValue ()
1140 		{
1141 			return Value;
1142 		}
1143 
GetValueAsLong()1144 		public override long GetValueAsLong ()
1145 		{
1146 			return Value;
1147 		}
1148 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
ConvertImplicitly(TypeSpec type)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>
TryImplicitIntConversion(TypeSpec target_type)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 
UIntConstant(BuiltinTypes types, uint v, Location loc)1294 		public UIntConstant (BuiltinTypes types, uint v, Location loc)
1295 			: this (types.UInt, v, loc)
1296 		{
1297 		}
1298 
UIntConstant(TypeSpec type, uint v, Location loc)1299 		public UIntConstant (TypeSpec type, uint v, Location loc)
1300 			: base (type, loc)
1301 		{
1302 			Value = v;
1303 		}
1304 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1305 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1306 		{
1307 			enc.Encode (Value);
1308 		}
1309 
Emit(EmitContext ec)1310 		public override void Emit (EmitContext ec)
1311 		{
1312 			ec.EmitInt (unchecked ((int) Value));
1313 		}
1314 
GetValue()1315 		public override object GetValue ()
1316 		{
1317 			return Value;
1318 		}
1319 
GetValueAsLong()1320 		public override long GetValueAsLong ()
1321 		{
1322 			return Value;
1323 		}
1324 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
LongConstant(BuiltinTypes types, long v, Location loc)1411 		public LongConstant (BuiltinTypes types, long v, Location loc)
1412 			: this (types.Long, v, loc)
1413 		{
1414 		}
1415 
LongConstant(TypeSpec type, long v, Location loc)1416 		public LongConstant (TypeSpec type, long v, Location loc)
1417 			: base (type, loc)
1418 		{
1419 			Value = v;
1420 		}
1421 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1422 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1423 		{
1424 			enc.Encode (Value);
1425 		}
1426 
Emit(EmitContext ec)1427 		public override void Emit (EmitContext ec)
1428 		{
1429 			ec.EmitLong (Value);
1430 		}
1431 
GetValue()1432 		public override object GetValue ()
1433 		{
1434 			return Value;
1435 		}
1436 
GetValueAsLong()1437 		public override long GetValueAsLong ()
1438 		{
1439 			return Value;
1440 		}
1441 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
ConvertImplicitly(TypeSpec type)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 
ULongConstant(BuiltinTypes types, ulong v, Location loc)1542 		public ULongConstant (BuiltinTypes types, ulong v, Location loc)
1543 			: this (types.ULong, v, loc)
1544 		{
1545 		}
1546 
ULongConstant(TypeSpec type, ulong v, Location loc)1547 		public ULongConstant (TypeSpec type, ulong v, Location loc)
1548 			: base (type, loc)
1549 		{
1550 			Value = v;
1551 		}
1552 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1553 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1554 		{
1555 			enc.Encode (Value);
1556 		}
1557 
Emit(EmitContext ec)1558 		public override void Emit (EmitContext ec)
1559 		{
1560 			ec.EmitLong (unchecked ((long) Value));
1561 		}
1562 
GetValue()1563 		public override object GetValue ()
1564 		{
1565 			return Value;
1566 		}
1567 
GetValueAsLong()1568 		public override long GetValueAsLong ()
1569 		{
1570 			return (long) Value;
1571 		}
1572 
Increment()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
FloatConstant(BuiltinTypes types, double v, Location loc)1655 		public FloatConstant (BuiltinTypes types, double v, Location loc)
1656 			: this (types.Float, v, loc)
1657 		{
1658 		}
1659 
FloatConstant(TypeSpec type, double v, Location loc)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 
ConvertImplicitly(TypeSpec type)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 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1677 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1678 		{
1679 			enc.Encode (Value);
1680 		}
1681 
Emit(EmitContext ec)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 
GetValue()1693 		public override object GetValue ()
1694 		{
1695 			return Value;
1696 		}
1697 
GetValueAsLiteral()1698 		public override string GetValueAsLiteral ()
1699 		{
1700 			return Value.ToString (CultureInfo.InvariantCulture);
1701 		}
1702 
GetValueAsLong()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
DoubleConstant(BuiltinTypes types, double v, Location loc)1792 		public DoubleConstant (BuiltinTypes types, double v, Location loc)
1793 			: this (types.Double, v, loc)
1794 		{
1795 		}
1796 
DoubleConstant(TypeSpec type, double v, Location loc)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 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)1806 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1807 		{
1808 			enc.Encode (Value);
1809 		}
1810 
Emit(EmitContext ec)1811 		public override void Emit (EmitContext ec)
1812 		{
1813 			ec.Emit (OpCodes.Ldc_R8, Value);
1814 		}
1815 
GetValue()1816 		public override object GetValue ()
1817 		{
1818 			return Value;
1819 		}
1820 
GetValueAsLiteral()1821 		public override string GetValueAsLiteral ()
1822 		{
1823 			return Value.ToString (CultureInfo.InvariantCulture);
1824 		}
1825 
GetValueAsLong()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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
DecimalConstant(BuiltinTypes types, decimal d, Location loc)1914 		public DecimalConstant (BuiltinTypes types, decimal d, Location loc)
1915 			: this (types.Decimal, d, loc)
1916 		{
1917 		}
1918 
DecimalConstant(TypeSpec type, decimal d, Location loc)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 
Emit(EmitContext ec)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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 
GetValue()2017 		public override object GetValue ()
2018 		{
2019 			return Value;
2020 		}
2021 
GetValueAsLiteral()2022 		public override string GetValueAsLiteral ()
2023 		{
2024 			return Value.ToString (CultureInfo.InvariantCulture) + "M";
2025 		}
2026 
GetValueAsLong()2027 		public override long GetValueAsLong ()
2028 		{
2029 			throw new NotSupportedException ();
2030 		}
2031 	}
2032 
2033 	public class StringConstant : Constant {
StringConstant(BuiltinTypes types, string s, Location loc)2034 		public StringConstant (BuiltinTypes types, string s, Location loc)
2035 			: this (types.String, s, loc)
2036 		{
2037 		}
2038 
StringConstant(TypeSpec type, string s, Location loc)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 
StringConstant(Location loc)2048 		protected StringConstant (Location loc)
2049 			: base (loc)
2050 		{
2051 		}
2052 
2053 		public string Value { get; protected set; }
2054 
GetValue()2055 		public override object GetValue ()
2056 		{
2057 			return Value;
2058 		}
2059 
GetValueAsLiteral()2060 		public override string GetValueAsLiteral ()
2061 		{
2062 			// FIXME: Escape the string.
2063 			return "\"" + Value + "\"";
2064 		}
2065 
GetValueAsLong()2066 		public override long GetValueAsLong ()
2067 		{
2068 			throw new NotSupportedException ();
2069 		}
2070 
Emit(EmitContext ec)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 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)2128 		public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
2129 		{
2130 			return null;
2131 		}
2132 
ConvertImplicitly(TypeSpec type)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 
NameOf(SimpleName name)2146 		public NameOf (SimpleName name)
2147 			: base (name.Location)
2148 		{
2149 			this.name = name;
2150 		}
2151 
DoResolve(ResolveContext rc)2152 		protected override Expression DoResolve (ResolveContext rc)
2153 		{
2154 			throw new NotSupportedException ();
2155 		}
2156 
ResolveArgumentExpression(ResolveContext rc, Expression expr)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 
IsLeftResolvedExpressionValid(Expression expr)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 
ResolveOverload(ResolveContext rc, Arguments args)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 	{
NullConstant(TypeSpec type, Location loc)2262 		public NullConstant (TypeSpec type, Location loc)
2263 			: base (loc)
2264 		{
2265 			eclass = ExprClass.Value;
2266 			this.type = type;
2267 		}
2268 
CreateExpressionTree(ResolveContext ec)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 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)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 
Emit(EmitContext ec)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 
ConvertExplicitly(bool inCheckedContext, TypeSpec targetType)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 
ConvertImplicitly(TypeSpec targetType)2345 		public override Constant ConvertImplicitly (TypeSpec targetType)
2346 		{
2347 			return ConvertExplicitly (false, targetType);
2348 		}
2349 
GetSignatureForError()2350 		public override string GetSignatureForError ()
2351 		{
2352 			return "null";
2353 		}
2354 
GetValue()2355 		public override object GetValue ()
2356 		{
2357 			return null;
2358 		}
2359 
GetValueAsLiteral()2360 		public override string GetValueAsLiteral ()
2361 		{
2362 			return GetSignatureForError ();
2363 		}
2364 
GetValueAsLong()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 	{
NullPointer(TypeSpec type, Location loc)2393 		public NullPointer (TypeSpec type, Location loc)
2394 			: base (type, loc)
2395 		{
2396 		}
2397 
CreateExpressionTree(ResolveContext ec)2398 		public override Expression CreateExpressionTree (ResolveContext ec)
2399 		{
2400 			Error_PointerInsideExpressionTree (ec);
2401 			return base.CreateExpressionTree (ec);
2402 		}
2403 
Emit(EmitContext ec)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 
SideEffectConstant(Constant value, Expression side_effect, Location loc)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 
ContainsEmitWithAwait()2442 		public override bool ContainsEmitWithAwait ()
2443 		{
2444 			return side_effect.ContainsEmitWithAwait ();
2445 		}
2446 
GetValue()2447 		public override object GetValue ()
2448 		{
2449 			return value.GetValue ();
2450 		}
2451 
GetValueAsLiteral()2452 		public override string GetValueAsLiteral ()
2453 		{
2454 			return value.GetValueAsLiteral ();
2455 		}
2456 
GetValueAsLong()2457 		public override long GetValueAsLong ()
2458 		{
2459 			return value.GetValueAsLong ();
2460 		}
2461 
Emit(EmitContext ec)2462 		public override void Emit (EmitContext ec)
2463 		{
2464 			side_effect.EmitSideEffect (ec);
2465 			value.Emit (ec);
2466 		}
2467 
EmitSideEffect(EmitContext ec)2468 		public override void EmitSideEffect (EmitContext ec)
2469 		{
2470 			side_effect.EmitSideEffect (ec);
2471 			value.EmitSideEffect (ec);
2472 		}
2473 
FlowAnalysis(FlowAnalysisContext fc)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 
ConvertExplicitly(bool in_checked_context, TypeSpec target_type)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 }
2504