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