826 lines
24 KiB
C#
826 lines
24 KiB
C#
using System;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
|
|
namespace System.Linq.Expressions
|
|
{
|
|
/// <summary>Represents an expression that has a binary operator.</summary>
|
|
// Token: 0x02000015 RID: 21
|
|
public sealed class BinaryExpression : Expression
|
|
{
|
|
// Token: 0x06000131 RID: 305 RVA: 0x000077B4 File Offset: 0x000059B4
|
|
internal BinaryExpression(ExpressionType node_type, Type type, Expression left, Expression right)
|
|
: base(node_type, type)
|
|
{
|
|
this.left = left;
|
|
this.right = right;
|
|
}
|
|
|
|
// Token: 0x06000132 RID: 306 RVA: 0x000077D0 File Offset: 0x000059D0
|
|
internal BinaryExpression(ExpressionType node_type, Type type, Expression left, Expression right, MethodInfo method)
|
|
: base(node_type, type)
|
|
{
|
|
this.left = left;
|
|
this.right = right;
|
|
this.method = method;
|
|
}
|
|
|
|
// Token: 0x06000133 RID: 307 RVA: 0x000077F4 File Offset: 0x000059F4
|
|
internal BinaryExpression(ExpressionType node_type, Type type, Expression left, Expression right, bool lift_to_null, bool is_lifted, MethodInfo method, LambdaExpression conversion)
|
|
: base(node_type, type)
|
|
{
|
|
this.left = left;
|
|
this.right = right;
|
|
this.method = method;
|
|
this.conversion = conversion;
|
|
this.lift_to_null = lift_to_null;
|
|
this.is_lifted = is_lifted;
|
|
}
|
|
|
|
/// <summary>Gets the left operand of the binary operation.</summary>
|
|
/// <returns>An <see cref="T:System.Linq.Expressions.Expression" /> that represents the left operand of the binary operation.</returns>
|
|
// Token: 0x17000011 RID: 17
|
|
// (get) Token: 0x06000134 RID: 308 RVA: 0x00007830 File Offset: 0x00005A30
|
|
public Expression Left
|
|
{
|
|
get
|
|
{
|
|
return this.left;
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets the right operand of the binary operation.</summary>
|
|
/// <returns>An <see cref="T:System.Linq.Expressions.Expression" /> that represents the right operand of the binary operation.</returns>
|
|
// Token: 0x17000012 RID: 18
|
|
// (get) Token: 0x06000135 RID: 309 RVA: 0x00007838 File Offset: 0x00005A38
|
|
public Expression Right
|
|
{
|
|
get
|
|
{
|
|
return this.right;
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets the implementing method for the binary operation.</summary>
|
|
/// <returns>The <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</returns>
|
|
// Token: 0x17000013 RID: 19
|
|
// (get) Token: 0x06000136 RID: 310 RVA: 0x00007840 File Offset: 0x00005A40
|
|
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: 0x17000014 RID: 20
|
|
// (get) Token: 0x06000137 RID: 311 RVA: 0x00007848 File Offset: 0x00005A48
|
|
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: 0x17000015 RID: 21
|
|
// (get) Token: 0x06000138 RID: 312 RVA: 0x00007850 File Offset: 0x00005A50
|
|
public bool IsLiftedToNull
|
|
{
|
|
get
|
|
{
|
|
return this.lift_to_null;
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets the type conversion function that is used by a coalescing operation.</summary>
|
|
/// <returns>A <see cref="T:System.Linq.Expressions.LambdaExpression" /> that represents a type conversion function.</returns>
|
|
// Token: 0x17000016 RID: 22
|
|
// (get) Token: 0x06000139 RID: 313 RVA: 0x00007858 File Offset: 0x00005A58
|
|
public LambdaExpression Conversion
|
|
{
|
|
get
|
|
{
|
|
return this.conversion;
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600013A RID: 314 RVA: 0x00007860 File Offset: 0x00005A60
|
|
private void EmitArrayAccess(EmitContext ec)
|
|
{
|
|
this.left.Emit(ec);
|
|
this.right.Emit(ec);
|
|
ec.ig.Emit(OpCodes.Ldelem, base.Type);
|
|
}
|
|
|
|
// Token: 0x0600013B RID: 315 RVA: 0x0000789C File Offset: 0x00005A9C
|
|
private void EmitLogicalBinary(EmitContext ec)
|
|
{
|
|
ExpressionType nodeType = base.NodeType;
|
|
if (nodeType != ExpressionType.And)
|
|
{
|
|
if (nodeType != ExpressionType.AndAlso)
|
|
{
|
|
if (nodeType == ExpressionType.Or)
|
|
{
|
|
goto IL_2A;
|
|
}
|
|
if (nodeType != ExpressionType.OrElse)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if (!this.IsLifted)
|
|
{
|
|
this.EmitLogicalShortCircuit(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitLiftedLogicalShortCircuit(ec);
|
|
}
|
|
return;
|
|
}
|
|
IL_2A:
|
|
if (!this.IsLifted)
|
|
{
|
|
this.EmitLogical(ec);
|
|
}
|
|
else if (base.Type == typeof(bool?))
|
|
{
|
|
this.EmitLiftedLogical(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitLiftedArithmeticBinary(ec);
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600013C RID: 316 RVA: 0x0000793C File Offset: 0x00005B3C
|
|
private void EmitLogical(EmitContext ec)
|
|
{
|
|
this.EmitNonLiftedBinary(ec);
|
|
}
|
|
|
|
// Token: 0x0600013D RID: 317 RVA: 0x00007948 File Offset: 0x00005B48
|
|
private void EmitLiftedLogical(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
bool flag = base.NodeType == ExpressionType.And;
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
Label label3 = ig.DefineLabel();
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ig.Emit(OpCodes.Brtrue, label);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
ig.Emit(OpCodes.Brtrue, label2);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, label);
|
|
ig.MarkLabel(label2);
|
|
ec.EmitLoad((!flag) ? localBuilder2 : localBuilder);
|
|
ig.Emit(OpCodes.Br, label3);
|
|
ig.MarkLabel(label);
|
|
ec.EmitLoad((!flag) ? localBuilder : localBuilder2);
|
|
ig.MarkLabel(label3);
|
|
}
|
|
|
|
// Token: 0x0600013E RID: 318 RVA: 0x00007A20 File Offset: 0x00005C20
|
|
private void EmitLogicalShortCircuit(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
bool flag = base.NodeType == ExpressionType.AndAlso;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
ec.Emit(this.left);
|
|
ig.Emit((!flag) ? OpCodes.Brtrue : OpCodes.Brfalse, label);
|
|
ec.Emit(this.right);
|
|
ig.Emit(OpCodes.Br, label2);
|
|
ig.MarkLabel(label);
|
|
ig.Emit((!flag) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
|
|
ig.MarkLabel(label2);
|
|
}
|
|
|
|
// Token: 0x0600013F RID: 319 RVA: 0x00007AB8 File Offset: 0x00005CB8
|
|
private MethodInfo GetFalseOperator()
|
|
{
|
|
return Expression.GetFalseOperator(this.left.Type.GetNotNullableType());
|
|
}
|
|
|
|
// Token: 0x06000140 RID: 320 RVA: 0x00007AD0 File Offset: 0x00005CD0
|
|
private MethodInfo GetTrueOperator()
|
|
{
|
|
return Expression.GetTrueOperator(this.left.Type.GetNotNullableType());
|
|
}
|
|
|
|
// Token: 0x06000141 RID: 321 RVA: 0x00007AE8 File Offset: 0x00005CE8
|
|
private void EmitUserDefinedLogicalShortCircuit(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
bool flag = base.NodeType == ExpressionType.AndAlso;
|
|
Label label = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
ec.EmitLoad(localBuilder);
|
|
ig.Emit(OpCodes.Dup);
|
|
ec.EmitCall((!flag) ? this.GetTrueOperator() : this.GetFalseOperator());
|
|
ig.Emit(OpCodes.Brtrue, label);
|
|
ec.Emit(this.right);
|
|
ec.EmitCall(this.method);
|
|
ig.MarkLabel(label);
|
|
}
|
|
|
|
// Token: 0x06000142 RID: 322 RVA: 0x00007B74 File Offset: 0x00005D74
|
|
private void EmitLiftedLogicalShortCircuit(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
bool flag = base.NodeType == ExpressionType.AndAlso;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
Label label3 = ig.DefineLabel();
|
|
Label label4 = ig.DefineLabel();
|
|
Label label5 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, label);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Ceq);
|
|
ig.Emit((!flag) ? OpCodes.Brfalse : OpCodes.Brtrue, label2);
|
|
ig.MarkLabel(label);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
ec.EmitNullableHasValue(localBuilder2);
|
|
ig.Emit(OpCodes.Brfalse_S, label3);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Ceq);
|
|
ig.Emit((!flag) ? OpCodes.Brfalse : OpCodes.Brtrue, label2);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, label3);
|
|
ig.Emit((!flag) ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
|
|
ig.Emit(OpCodes.Br_S, label4);
|
|
ig.MarkLabel(label2);
|
|
ig.Emit((!flag) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
|
|
ig.MarkLabel(label4);
|
|
ec.EmitNullableNew(base.Type);
|
|
ig.Emit(OpCodes.Br, label5);
|
|
ig.MarkLabel(label3);
|
|
LocalBuilder localBuilder3 = ig.DeclareLocal(base.Type);
|
|
ec.EmitNullableInitialize(localBuilder3);
|
|
ig.MarkLabel(label5);
|
|
}
|
|
|
|
// Token: 0x06000143 RID: 323 RVA: 0x00007D20 File Offset: 0x00005F20
|
|
private void EmitCoalesce(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
bool flag = localBuilder.LocalType.IsNullable();
|
|
if (flag)
|
|
{
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
}
|
|
else
|
|
{
|
|
ec.EmitLoad(localBuilder);
|
|
}
|
|
ig.Emit(OpCodes.Brfalse, label2);
|
|
if (flag && !base.Type.IsNullable())
|
|
{
|
|
ec.EmitNullableGetValue(localBuilder);
|
|
}
|
|
else
|
|
{
|
|
ec.EmitLoad(localBuilder);
|
|
}
|
|
ig.Emit(OpCodes.Br, label);
|
|
ig.MarkLabel(label2);
|
|
ec.Emit(this.right);
|
|
ig.MarkLabel(label);
|
|
}
|
|
|
|
// Token: 0x06000144 RID: 324 RVA: 0x00007DD4 File Offset: 0x00005FD4
|
|
private void EmitConvertedCoalesce(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
if (localBuilder.LocalType.IsNullable())
|
|
{
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
}
|
|
else
|
|
{
|
|
ec.EmitLoad(localBuilder);
|
|
}
|
|
ig.Emit(OpCodes.Brfalse, label2);
|
|
ec.Emit(this.conversion);
|
|
ec.EmitLoad(localBuilder);
|
|
ig.Emit(OpCodes.Callvirt, this.conversion.Type.GetInvokeMethod());
|
|
ig.Emit(OpCodes.Br, label);
|
|
ig.MarkLabel(label2);
|
|
ec.Emit(this.right);
|
|
ig.MarkLabel(label);
|
|
}
|
|
|
|
// Token: 0x06000145 RID: 325 RVA: 0x00007E88 File Offset: 0x00006088
|
|
private static bool IsInt32OrInt64(Type type)
|
|
{
|
|
return type == typeof(int) || type == typeof(long);
|
|
}
|
|
|
|
// Token: 0x06000146 RID: 326 RVA: 0x00007EB8 File Offset: 0x000060B8
|
|
private static bool IsSingleOrDouble(Type type)
|
|
{
|
|
return type == typeof(float) || type == typeof(double);
|
|
}
|
|
|
|
// Token: 0x06000147 RID: 327 RVA: 0x00007EE8 File Offset: 0x000060E8
|
|
private void EmitBinaryOperator(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
bool flag = Expression.IsUnsigned(this.left.Type);
|
|
ExpressionType nodeType = base.NodeType;
|
|
switch (nodeType)
|
|
{
|
|
case ExpressionType.Divide:
|
|
ig.Emit((!flag) ? OpCodes.Div : OpCodes.Div_Un);
|
|
break;
|
|
case ExpressionType.Equal:
|
|
ig.Emit(OpCodes.Ceq);
|
|
break;
|
|
case ExpressionType.ExclusiveOr:
|
|
ig.Emit(OpCodes.Xor);
|
|
break;
|
|
case ExpressionType.GreaterThan:
|
|
ig.Emit((!flag) ? OpCodes.Cgt : OpCodes.Cgt_Un);
|
|
break;
|
|
case ExpressionType.GreaterThanOrEqual:
|
|
if (flag || BinaryExpression.IsSingleOrDouble(this.left.Type))
|
|
{
|
|
ig.Emit(OpCodes.Clt_Un);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Clt);
|
|
}
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Ceq);
|
|
break;
|
|
default:
|
|
switch (nodeType)
|
|
{
|
|
case ExpressionType.Add:
|
|
ig.Emit(OpCodes.Add);
|
|
break;
|
|
case ExpressionType.AddChecked:
|
|
if (BinaryExpression.IsInt32OrInt64(this.left.Type))
|
|
{
|
|
ig.Emit(OpCodes.Add_Ovf);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit((!flag) ? OpCodes.Add : OpCodes.Add_Ovf_Un);
|
|
}
|
|
break;
|
|
case ExpressionType.And:
|
|
ig.Emit(OpCodes.And);
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException(string.Format("Internal error: BinaryExpression contains non-Binary nodetype {0}", base.NodeType));
|
|
}
|
|
break;
|
|
case ExpressionType.LeftShift:
|
|
case ExpressionType.RightShift:
|
|
ig.Emit(OpCodes.Ldc_I4, (this.left.Type != typeof(int)) ? 63 : 31);
|
|
ig.Emit(OpCodes.And);
|
|
if (base.NodeType == ExpressionType.RightShift)
|
|
{
|
|
ig.Emit((!flag) ? OpCodes.Shr : OpCodes.Shr_Un);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Shl);
|
|
}
|
|
break;
|
|
case ExpressionType.LessThan:
|
|
ig.Emit((!flag) ? OpCodes.Clt : OpCodes.Clt_Un);
|
|
break;
|
|
case ExpressionType.LessThanOrEqual:
|
|
if (flag || BinaryExpression.IsSingleOrDouble(this.left.Type))
|
|
{
|
|
ig.Emit(OpCodes.Cgt_Un);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Cgt);
|
|
}
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Ceq);
|
|
break;
|
|
case ExpressionType.Modulo:
|
|
ig.Emit((!flag) ? OpCodes.Rem : OpCodes.Rem_Un);
|
|
break;
|
|
case ExpressionType.Multiply:
|
|
ig.Emit(OpCodes.Mul);
|
|
break;
|
|
case ExpressionType.MultiplyChecked:
|
|
if (BinaryExpression.IsInt32OrInt64(this.left.Type))
|
|
{
|
|
ig.Emit(OpCodes.Mul_Ovf);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit((!flag) ? OpCodes.Mul : OpCodes.Mul_Ovf_Un);
|
|
}
|
|
break;
|
|
case ExpressionType.NotEqual:
|
|
ig.Emit(OpCodes.Ceq);
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Ceq);
|
|
break;
|
|
case ExpressionType.Or:
|
|
ig.Emit(OpCodes.Or);
|
|
break;
|
|
case ExpressionType.Power:
|
|
ig.Emit(OpCodes.Call, typeof(Math).GetMethod("Pow"));
|
|
break;
|
|
case ExpressionType.Subtract:
|
|
ig.Emit(OpCodes.Sub);
|
|
break;
|
|
case ExpressionType.SubtractChecked:
|
|
if (BinaryExpression.IsInt32OrInt64(this.left.Type))
|
|
{
|
|
ig.Emit(OpCodes.Sub_Ovf);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit((!flag) ? OpCodes.Sub : OpCodes.Sub_Ovf_Un);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000148 RID: 328 RVA: 0x000082F0 File Offset: 0x000064F0
|
|
private bool IsLeftLiftedBinary()
|
|
{
|
|
return this.left.Type.IsNullable() && !this.right.Type.IsNullable();
|
|
}
|
|
|
|
// Token: 0x06000149 RID: 329 RVA: 0x00008328 File Offset: 0x00006528
|
|
private void EmitLeftLiftedToNullBinary(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, label);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.Emit(this.right);
|
|
this.EmitBinaryOperator(ec);
|
|
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: 0x0600014A RID: 330 RVA: 0x000083C0 File Offset: 0x000065C0
|
|
private void EmitLiftedArithmeticBinary(EmitContext ec)
|
|
{
|
|
if (this.IsLeftLiftedBinary())
|
|
{
|
|
this.EmitLeftLiftedToNullBinary(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitLiftedToNullBinary(ec);
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600014B RID: 331 RVA: 0x000083E0 File Offset: 0x000065E0
|
|
private void EmitLiftedToNullBinary(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
LocalBuilder localBuilder3 = ig.DeclareLocal(base.Type);
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ec.EmitNullableHasValue(localBuilder2);
|
|
ig.Emit(OpCodes.And);
|
|
ig.Emit(OpCodes.Brtrue, label);
|
|
ec.EmitNullableInitialize(localBuilder3);
|
|
ig.Emit(OpCodes.Br, label2);
|
|
ig.MarkLabel(label);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
this.EmitBinaryOperator(ec);
|
|
ec.EmitNullableNew(localBuilder3.LocalType);
|
|
ig.MarkLabel(label2);
|
|
}
|
|
|
|
// Token: 0x0600014C RID: 332 RVA: 0x00008498 File Offset: 0x00006698
|
|
private void EmitLiftedRelationalBinary(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
ExpressionType expressionType = base.NodeType;
|
|
if (expressionType != ExpressionType.Equal && expressionType != ExpressionType.NotEqual)
|
|
{
|
|
this.EmitBinaryOperator(ec);
|
|
ig.Emit(OpCodes.Brfalse, label);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Bne_Un, label);
|
|
}
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ec.EmitNullableHasValue(localBuilder2);
|
|
expressionType = base.NodeType;
|
|
if (expressionType != ExpressionType.Equal)
|
|
{
|
|
if (expressionType != ExpressionType.NotEqual)
|
|
{
|
|
ig.Emit(OpCodes.And);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Ceq);
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Ceq);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Ceq);
|
|
}
|
|
ig.Emit(OpCodes.Br, label2);
|
|
ig.MarkLabel(label);
|
|
ig.Emit((base.NodeType != ExpressionType.NotEqual) ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
|
|
ig.MarkLabel(label2);
|
|
}
|
|
|
|
// Token: 0x0600014D RID: 333 RVA: 0x000085DC File Offset: 0x000067DC
|
|
private void EmitArithmeticBinary(EmitContext ec)
|
|
{
|
|
if (!this.IsLifted)
|
|
{
|
|
this.EmitNonLiftedBinary(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitLiftedArithmeticBinary(ec);
|
|
}
|
|
}
|
|
|
|
// Token: 0x0600014E RID: 334 RVA: 0x000085FC File Offset: 0x000067FC
|
|
private void EmitNonLiftedBinary(EmitContext ec)
|
|
{
|
|
ec.Emit(this.left);
|
|
ec.Emit(this.right);
|
|
this.EmitBinaryOperator(ec);
|
|
}
|
|
|
|
// Token: 0x0600014F RID: 335 RVA: 0x00008620 File Offset: 0x00006820
|
|
private void EmitRelationalBinary(EmitContext ec)
|
|
{
|
|
if (!this.IsLifted)
|
|
{
|
|
this.EmitNonLiftedBinary(ec);
|
|
}
|
|
else if (this.IsLiftedToNull)
|
|
{
|
|
this.EmitLiftedToNullBinary(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitLiftedRelationalBinary(ec);
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000150 RID: 336 RVA: 0x00008664 File Offset: 0x00006864
|
|
private void EmitLiftedUserDefinedOperator(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
Label label3 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ec.EmitNullableHasValue(localBuilder2);
|
|
ExpressionType nodeType = base.NodeType;
|
|
if (nodeType != ExpressionType.Equal)
|
|
{
|
|
if (nodeType != ExpressionType.NotEqual)
|
|
{
|
|
ig.Emit(OpCodes.And);
|
|
ig.Emit(OpCodes.Brfalse, label2);
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Bne_Un, label);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, label2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ig.Emit(OpCodes.Bne_Un, label2);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, label);
|
|
}
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
ec.EmitCall(this.method);
|
|
ig.Emit(OpCodes.Br, label3);
|
|
ig.MarkLabel(label);
|
|
ig.Emit(OpCodes.Ldc_I4_1);
|
|
ig.Emit(OpCodes.Br, label3);
|
|
ig.MarkLabel(label2);
|
|
ig.Emit(OpCodes.Ldc_I4_0);
|
|
ig.Emit(OpCodes.Br, label3);
|
|
ig.MarkLabel(label3);
|
|
}
|
|
|
|
// Token: 0x06000151 RID: 337 RVA: 0x000087AC File Offset: 0x000069AC
|
|
private void EmitLiftedToNullUserDefinedOperator(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ec.EmitNullableHasValue(localBuilder2);
|
|
ig.Emit(OpCodes.And);
|
|
ig.Emit(OpCodes.Brfalse, label);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
ec.EmitCall(this.method);
|
|
ec.EmitNullableNew(base.Type);
|
|
ig.Emit(OpCodes.Br, label2);
|
|
ig.MarkLabel(label);
|
|
LocalBuilder localBuilder3 = ig.DeclareLocal(base.Type);
|
|
ec.EmitNullableInitialize(localBuilder3);
|
|
ig.MarkLabel(label2);
|
|
}
|
|
|
|
// Token: 0x06000152 RID: 338 RVA: 0x00008868 File Offset: 0x00006A68
|
|
private void EmitUserDefinedLiftedLogicalShortCircuit(EmitContext ec)
|
|
{
|
|
ILGenerator ig = ec.ig;
|
|
bool flag = base.NodeType == ExpressionType.AndAlso;
|
|
Label label = ig.DefineLabel();
|
|
Label label2 = ig.DefineLabel();
|
|
Label label3 = ig.DefineLabel();
|
|
Label label4 = ig.DefineLabel();
|
|
LocalBuilder localBuilder = ec.EmitStored(this.left);
|
|
ec.EmitNullableHasValue(localBuilder);
|
|
ig.Emit(OpCodes.Brfalse, (!flag) ? label : label3);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.EmitCall((!flag) ? this.GetTrueOperator() : this.GetFalseOperator());
|
|
ig.Emit(OpCodes.Brtrue, label2);
|
|
ig.MarkLabel(label);
|
|
LocalBuilder localBuilder2 = ec.EmitStored(this.right);
|
|
ec.EmitNullableHasValue(localBuilder2);
|
|
ig.Emit(OpCodes.Brfalse, label3);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder);
|
|
ec.EmitNullableGetValueOrDefault(localBuilder2);
|
|
ec.EmitCall(this.method);
|
|
ec.EmitNullableNew(base.Type);
|
|
ig.Emit(OpCodes.Br, label4);
|
|
ig.MarkLabel(label2);
|
|
ec.EmitLoad(localBuilder);
|
|
ig.Emit(OpCodes.Br, label4);
|
|
ig.MarkLabel(label3);
|
|
LocalBuilder localBuilder3 = ig.DeclareLocal(base.Type);
|
|
ec.EmitNullableInitialize(localBuilder3);
|
|
ig.MarkLabel(label4);
|
|
}
|
|
|
|
// Token: 0x06000153 RID: 339 RVA: 0x000089A8 File Offset: 0x00006BA8
|
|
private void EmitUserDefinedOperator(EmitContext ec)
|
|
{
|
|
if (!this.IsLifted)
|
|
{
|
|
ExpressionType expressionType = base.NodeType;
|
|
if (expressionType != ExpressionType.AndAlso && expressionType != ExpressionType.OrElse)
|
|
{
|
|
this.left.Emit(ec);
|
|
this.right.Emit(ec);
|
|
ec.EmitCall(this.method);
|
|
}
|
|
else
|
|
{
|
|
this.EmitUserDefinedLogicalShortCircuit(ec);
|
|
}
|
|
}
|
|
else if (this.IsLiftedToNull)
|
|
{
|
|
ExpressionType expressionType = base.NodeType;
|
|
if (expressionType != ExpressionType.AndAlso && expressionType != ExpressionType.OrElse)
|
|
{
|
|
this.EmitLiftedToNullUserDefinedOperator(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitUserDefinedLiftedLogicalShortCircuit(ec);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.EmitLiftedUserDefinedOperator(ec);
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000154 RID: 340 RVA: 0x00008A60 File Offset: 0x00006C60
|
|
internal override void Emit(EmitContext ec)
|
|
{
|
|
if (this.method != null)
|
|
{
|
|
this.EmitUserDefinedOperator(ec);
|
|
return;
|
|
}
|
|
switch (base.NodeType)
|
|
{
|
|
case ExpressionType.Add:
|
|
case ExpressionType.AddChecked:
|
|
case ExpressionType.Divide:
|
|
case ExpressionType.ExclusiveOr:
|
|
case ExpressionType.LeftShift:
|
|
case ExpressionType.Modulo:
|
|
case ExpressionType.Multiply:
|
|
case ExpressionType.MultiplyChecked:
|
|
case ExpressionType.Power:
|
|
case ExpressionType.RightShift:
|
|
case ExpressionType.Subtract:
|
|
case ExpressionType.SubtractChecked:
|
|
this.EmitArithmeticBinary(ec);
|
|
return;
|
|
case ExpressionType.And:
|
|
case ExpressionType.AndAlso:
|
|
case ExpressionType.Or:
|
|
case ExpressionType.OrElse:
|
|
this.EmitLogicalBinary(ec);
|
|
return;
|
|
case ExpressionType.ArrayIndex:
|
|
this.EmitArrayAccess(ec);
|
|
return;
|
|
case ExpressionType.Coalesce:
|
|
if (this.conversion != null)
|
|
{
|
|
this.EmitConvertedCoalesce(ec);
|
|
}
|
|
else
|
|
{
|
|
this.EmitCoalesce(ec);
|
|
}
|
|
return;
|
|
case ExpressionType.Equal:
|
|
case ExpressionType.GreaterThan:
|
|
case ExpressionType.GreaterThanOrEqual:
|
|
case ExpressionType.LessThan:
|
|
case ExpressionType.LessThanOrEqual:
|
|
case ExpressionType.NotEqual:
|
|
this.EmitRelationalBinary(ec);
|
|
return;
|
|
}
|
|
throw new NotSupportedException(base.NodeType.ToString());
|
|
}
|
|
|
|
// Token: 0x04000058 RID: 88
|
|
private Expression left;
|
|
|
|
// Token: 0x04000059 RID: 89
|
|
private Expression right;
|
|
|
|
// Token: 0x0400005A RID: 90
|
|
private LambdaExpression conversion;
|
|
|
|
// Token: 0x0400005B RID: 91
|
|
private MethodInfo method;
|
|
|
|
// Token: 0x0400005C RID: 92
|
|
private bool lift_to_null;
|
|
|
|
// Token: 0x0400005D RID: 93
|
|
private bool is_lifted;
|
|
}
|
|
}
|