using System; using System.Reflection; using System.Reflection.Emit; namespace System.Linq.Expressions { /// Represents an expression that has a unary operator. // Token: 0x02000030 RID: 48 public sealed class UnaryExpression : Expression { // Token: 0x06000251 RID: 593 RVA: 0x0000C180 File Offset: 0x0000A380 internal UnaryExpression(ExpressionType node_type, Expression operand, Type type) : base(node_type, type) { this.operand = operand; } // Token: 0x06000252 RID: 594 RVA: 0x0000C194 File Offset: 0x0000A394 internal UnaryExpression(ExpressionType node_type, Expression operand, Type type, MethodInfo method, bool is_lifted) : base(node_type, type) { this.operand = operand; this.method = method; this.is_lifted = is_lifted; } /// Gets the operand of the unary operation. /// An that represents the operand of the unary operation. // Token: 0x17000036 RID: 54 // (get) Token: 0x06000253 RID: 595 RVA: 0x0000C1B8 File Offset: 0x0000A3B8 public Expression Operand { get { return this.operand; } } /// Gets the implementing method for the unary operation. /// The that represents the implementing method. // Token: 0x17000037 RID: 55 // (get) Token: 0x06000254 RID: 596 RVA: 0x0000C1C0 File Offset: 0x0000A3C0 public MethodInfo Method { get { return this.method; } } /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator. /// true if the node represents a lifted call; otherwise, false. // Token: 0x17000038 RID: 56 // (get) Token: 0x06000255 RID: 597 RVA: 0x0000C1C8 File Offset: 0x0000A3C8 public bool IsLifted { get { return this.is_lifted; } } /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator whose return type is lifted to a nullable type. /// true if the operator's return type is lifted to a nullable type; otherwise, false. // Token: 0x17000039 RID: 57 // (get) Token: 0x06000256 RID: 598 RVA: 0x0000C1D0 File Offset: 0x0000A3D0 public bool IsLiftedToNull { get { return this.is_lifted && base.Type.IsNullable(); } } // Token: 0x06000257 RID: 599 RVA: 0x0000C1EC File Offset: 0x0000A3EC private void EmitArrayLength(EmitContext ec) { this.operand.Emit(ec); ec.ig.Emit(OpCodes.Ldlen); } // Token: 0x06000258 RID: 600 RVA: 0x0000C20C File Offset: 0x0000A40C private void EmitTypeAs(EmitContext ec) { Type type = base.Type; ec.EmitIsInst(this.operand, type); if (type.IsNullable()) { ec.ig.Emit(OpCodes.Unbox_Any, type); } } // Token: 0x06000259 RID: 601 RVA: 0x0000C24C File Offset: 0x0000A44C private void EmitLiftedUnary(EmitContext ec) { ILGenerator ig = ec.ig; LocalBuilder localBuilder = ec.EmitStored(this.operand); LocalBuilder localBuilder2 = ig.DeclareLocal(base.Type); Label label = ig.DefineLabel(); Label label2 = ig.DefineLabel(); ec.EmitNullableHasValue(localBuilder); ig.Emit(OpCodes.Brtrue, label); ec.EmitNullableInitialize(localBuilder2); ig.Emit(OpCodes.Br, label2); ig.MarkLabel(label); ec.EmitNullableGetValueOrDefault(localBuilder); this.EmitUnaryOperator(ec); ec.EmitNullableNew(base.Type); ig.MarkLabel(label2); } // Token: 0x0600025A RID: 602 RVA: 0x0000C2DC File Offset: 0x0000A4DC private void EmitUnaryOperator(EmitContext ec) { ILGenerator ig = ec.ig; ExpressionType nodeType = base.NodeType; switch (nodeType) { case ExpressionType.Negate: ig.Emit(OpCodes.Neg); break; default: if (nodeType != ExpressionType.Convert && nodeType != ExpressionType.ConvertChecked) { if (nodeType == ExpressionType.Not) { if (this.operand.Type.GetNotNullableType() == typeof(bool)) { ig.Emit(OpCodes.Ldc_I4_0); ig.Emit(OpCodes.Ceq); } else { ig.Emit(OpCodes.Not); } } } else { this.EmitPrimitiveConversion(ec, this.operand.Type.GetNotNullableType(), base.Type.GetNotNullableType()); } break; case ExpressionType.NegateChecked: ig.Emit(OpCodes.Ldc_I4_M1); ig.Emit((!Expression.IsUnsigned(this.operand.Type)) ? OpCodes.Mul_Ovf : OpCodes.Mul_Ovf_Un); break; } } // Token: 0x0600025B RID: 603 RVA: 0x0000C3E4 File Offset: 0x0000A5E4 private void EmitConvert(EmitContext ec) { Type type = this.operand.Type; Type type2 = base.Type; if (type == type2) { this.operand.Emit(ec); } else if (type.IsNullable() && !type2.IsNullable()) { this.EmitConvertFromNullable(ec); } else if (!type.IsNullable() && type2.IsNullable()) { this.EmitConvertToNullable(ec); } else if (type.IsNullable() && type2.IsNullable()) { this.EmitConvertFromNullableToNullable(ec); } else if (Expression.IsReferenceConversion(type, type2)) { this.EmitCast(ec); } else { if (!Expression.IsPrimitiveConversion(type, type2)) { throw new NotImplementedException(); } this.EmitPrimitiveConversion(ec); } } // Token: 0x0600025C RID: 604 RVA: 0x0000C4B8 File Offset: 0x0000A6B8 private void EmitConvertFromNullableToNullable(EmitContext ec) { this.EmitLiftedUnary(ec); } // Token: 0x0600025D RID: 605 RVA: 0x0000C4C4 File Offset: 0x0000A6C4 private void EmitConvertToNullable(EmitContext ec) { ec.Emit(this.operand); if (this.IsUnBoxing()) { this.EmitUnbox(ec); return; } if (this.operand.Type != base.Type.GetNotNullableType()) { this.EmitPrimitiveConversion(ec, this.operand.Type, base.Type.GetNotNullableType()); } ec.EmitNullableNew(base.Type); } // Token: 0x0600025E RID: 606 RVA: 0x0000C534 File Offset: 0x0000A734 private void EmitConvertFromNullable(EmitContext ec) { if (this.IsBoxing()) { ec.Emit(this.operand); this.EmitBox(ec); return; } ec.EmitCall(this.operand, this.operand.Type.GetMethod("get_Value")); if (this.operand.Type.GetNotNullableType() != base.Type) { this.EmitPrimitiveConversion(ec, this.operand.Type.GetNotNullableType(), base.Type); } } // Token: 0x0600025F RID: 607 RVA: 0x0000C5BC File Offset: 0x0000A7BC private bool IsBoxing() { return this.operand.Type.IsValueType && !base.Type.IsValueType; } // Token: 0x06000260 RID: 608 RVA: 0x0000C5F0 File Offset: 0x0000A7F0 private void EmitBox(EmitContext ec) { ec.ig.Emit(OpCodes.Box, this.operand.Type); } // Token: 0x06000261 RID: 609 RVA: 0x0000C610 File Offset: 0x0000A810 private bool IsUnBoxing() { return !this.operand.Type.IsValueType && base.Type.IsValueType; } // Token: 0x06000262 RID: 610 RVA: 0x0000C640 File Offset: 0x0000A840 private void EmitUnbox(EmitContext ec) { ec.ig.Emit(OpCodes.Unbox_Any, base.Type); } // Token: 0x06000263 RID: 611 RVA: 0x0000C658 File Offset: 0x0000A858 private void EmitCast(EmitContext ec) { this.operand.Emit(ec); if (this.IsBoxing()) { this.EmitBox(ec); } else if (this.IsUnBoxing()) { this.EmitUnbox(ec); } else { ec.ig.Emit(OpCodes.Castclass, base.Type); } } // Token: 0x06000264 RID: 612 RVA: 0x0000C6B8 File Offset: 0x0000A8B8 private void EmitPrimitiveConversion(EmitContext ec, bool is_unsigned, OpCode signed, OpCode unsigned, OpCode signed_checked, OpCode unsigned_checked) { if (base.NodeType != ExpressionType.ConvertChecked) { ec.ig.Emit((!is_unsigned) ? signed : unsigned); } else { ec.ig.Emit((!is_unsigned) ? signed_checked : unsigned_checked); } } // Token: 0x06000265 RID: 613 RVA: 0x0000C70C File Offset: 0x0000A90C private void EmitPrimitiveConversion(EmitContext ec) { this.operand.Emit(ec); this.EmitPrimitiveConversion(ec, this.operand.Type, base.Type); } // Token: 0x06000266 RID: 614 RVA: 0x0000C740 File Offset: 0x0000A940 private void EmitPrimitiveConversion(EmitContext ec, Type from, Type to) { bool flag = Expression.IsUnsigned(from); switch (Type.GetTypeCode(to)) { case TypeCode.SByte: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I1, OpCodes.Conv_U1, OpCodes.Conv_Ovf_I1, OpCodes.Conv_Ovf_I1_Un); return; case TypeCode.Byte: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I1, OpCodes.Conv_U1, OpCodes.Conv_Ovf_U1, OpCodes.Conv_Ovf_U1_Un); return; case TypeCode.Int16: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I2, OpCodes.Conv_U2, OpCodes.Conv_Ovf_I2, OpCodes.Conv_Ovf_I2_Un); return; case TypeCode.UInt16: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I2, OpCodes.Conv_U2, OpCodes.Conv_Ovf_U2, OpCodes.Conv_Ovf_U2_Un); return; case TypeCode.Int32: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I4, OpCodes.Conv_U4, OpCodes.Conv_Ovf_I4, OpCodes.Conv_Ovf_I4_Un); return; case TypeCode.UInt32: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I4, OpCodes.Conv_U4, OpCodes.Conv_Ovf_U4, OpCodes.Conv_Ovf_U4_Un); return; case TypeCode.Int64: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I8, OpCodes.Conv_U8, OpCodes.Conv_Ovf_I8, OpCodes.Conv_Ovf_I8_Un); return; case TypeCode.UInt64: this.EmitPrimitiveConversion(ec, flag, OpCodes.Conv_I8, OpCodes.Conv_U8, OpCodes.Conv_Ovf_U8, OpCodes.Conv_Ovf_U8_Un); return; case TypeCode.Single: if (flag) { ec.ig.Emit(OpCodes.Conv_R_Un); } ec.ig.Emit(OpCodes.Conv_R4); return; case TypeCode.Double: if (flag) { ec.ig.Emit(OpCodes.Conv_R_Un); } ec.ig.Emit(OpCodes.Conv_R8); return; default: throw new NotImplementedException(base.Type.ToString()); } } // Token: 0x06000267 RID: 615 RVA: 0x0000C8D8 File Offset: 0x0000AAD8 private void EmitArithmeticUnary(EmitContext ec) { if (!this.IsLifted) { this.operand.Emit(ec); this.EmitUnaryOperator(ec); } else { this.EmitLiftedUnary(ec); } } // Token: 0x06000268 RID: 616 RVA: 0x0000C910 File Offset: 0x0000AB10 private void EmitUserDefinedLiftedToNullOperator(EmitContext ec) { ILGenerator ig = ec.ig; LocalBuilder localBuilder = ec.EmitStored(this.operand); Label label = ig.DefineLabel(); Label label2 = ig.DefineLabel(); ec.EmitNullableHasValue(localBuilder); ig.Emit(OpCodes.Brfalse, label); ec.EmitNullableGetValueOrDefault(localBuilder); ec.EmitCall(this.method); ec.EmitNullableNew(base.Type); ig.Emit(OpCodes.Br, label2); ig.MarkLabel(label); LocalBuilder localBuilder2 = ig.DeclareLocal(base.Type); ec.EmitNullableInitialize(localBuilder2); ig.MarkLabel(label2); } // Token: 0x06000269 RID: 617 RVA: 0x0000C9A4 File Offset: 0x0000ABA4 private void EmitUserDefinedLiftedOperator(EmitContext ec) { LocalBuilder localBuilder = ec.EmitStored(this.operand); ec.EmitNullableGetValue(localBuilder); ec.EmitCall(this.method); } // Token: 0x0600026A RID: 618 RVA: 0x0000C9D4 File Offset: 0x0000ABD4 private void EmitUserDefinedOperator(EmitContext ec) { if (!this.IsLifted) { ec.Emit(this.operand); ec.EmitCall(this.method); } else if (this.IsLiftedToNull) { this.EmitUserDefinedLiftedToNullOperator(ec); } else { this.EmitUserDefinedLiftedOperator(ec); } } // Token: 0x0600026B RID: 619 RVA: 0x0000CA28 File Offset: 0x0000AC28 private void EmitQuote(EmitContext ec) { ec.EmitScope(); ec.EmitReadGlobal(this.operand, typeof(Expression)); if (ec.HasHoistedLocals) { ec.EmitLoadHoistedLocalsStore(); } else { ec.ig.Emit(OpCodes.Ldnull); } ec.EmitIsolateExpression(); } // Token: 0x0600026C RID: 620 RVA: 0x0000CA80 File Offset: 0x0000AC80 internal override void Emit(EmitContext ec) { if (this.method != null) { this.EmitUserDefinedOperator(ec); return; } ExpressionType nodeType = base.NodeType; switch (nodeType) { case ExpressionType.Negate: case ExpressionType.UnaryPlus: case ExpressionType.NegateChecked: case ExpressionType.Not: this.EmitArithmeticUnary(ec); return; default: if (nodeType == ExpressionType.Convert || nodeType == ExpressionType.ConvertChecked) { this.EmitConvert(ec); return; } if (nodeType == ExpressionType.ArrayLength) { this.EmitArrayLength(ec); return; } if (nodeType == ExpressionType.Quote) { this.EmitQuote(ec); return; } if (nodeType != ExpressionType.TypeAs) { throw new NotImplementedException(base.NodeType.ToString()); } this.EmitTypeAs(ec); return; } } // Token: 0x040000C0 RID: 192 private Expression operand; // Token: 0x040000C1 RID: 193 private MethodInfo method; // Token: 0x040000C2 RID: 194 private bool is_lifted; } }