Files
Dec2017-Script-Dump/System.Core/System/Linq/Expressions/UnaryExpression.cs
T
2026-06-04 11:42:34 +02:00

461 lines
13 KiB
C#

using System;
using System.Reflection;
using System.Reflection.Emit;
namespace System.Linq.Expressions
{
/// <summary>Represents an expression that has a unary operator.</summary>
// 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;
}
/// <summary>Gets the operand of the unary operation.</summary>
/// <returns>An <see cref="T:System.Linq.Expressions.Expression" /> that represents the operand of the unary operation.</returns>
// Token: 0x17000036 RID: 54
// (get) Token: 0x06000253 RID: 595 RVA: 0x0000C1B8 File Offset: 0x0000A3B8
public Expression Operand
{
get
{
return this.operand;
}
}
/// <summary>Gets the implementing method for the unary operation.</summary>
/// <returns>The <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</returns>
// Token: 0x17000037 RID: 55
// (get) Token: 0x06000254 RID: 596 RVA: 0x0000C1C0 File Offset: 0x0000A3C0
public MethodInfo Method
{
get
{
return this.method;
}
}
/// <summary>Gets a value that indicates whether the expression tree node represents a lifted call to an operator.</summary>
/// <returns>true if the node represents a lifted call; otherwise, false.</returns>
// Token: 0x17000038 RID: 56
// (get) Token: 0x06000255 RID: 597 RVA: 0x0000C1C8 File Offset: 0x0000A3C8
public bool IsLifted
{
get
{
return this.is_lifted;
}
}
/// <summary>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.</summary>
/// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
// 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;
}
}