/// <summary> /// Reduces the expression node to a simpler expression. /// </summary> /// <returns>The reduced expression.</returns> public override Expression Reduce() { var functionalOp = new Func<Expression, Expression>(lhs => { var operation = default(ExpressionType); switch (OperationNodeType) { case CSharpExpressionType.PreIncrementAssign: case CSharpExpressionType.PreIncrementAssignChecked: case CSharpExpressionType.PostIncrementAssign: case CSharpExpressionType.PostIncrementAssignChecked: operation = ExpressionType.Increment; break; case CSharpExpressionType.PreDecrementAssign: case CSharpExpressionType.PreDecrementAssignChecked: case CSharpExpressionType.PostDecrementAssign: case CSharpExpressionType.PostDecrementAssignChecked: operation = ExpressionType.Decrement; break; default: throw ContractUtils.Unreachable; } var args = new[] { CSharpArgumentInfo.Create(Operand.Flags, null) }; var binder = Binder.UnaryOperation(Flags, operation, Context, args); var dynamic = DynamicHelpers.MakeDynamic(typeof(object), binder, new[] { lhs }, new[] { lhs.Type }); // NB: no conversion needed in the unary case return dynamic; }); var flags = Flags | CSharpBinderFlags.ValueFromCompoundAssignment; var res = DynamicHelpers.ReduceDynamicAssignment(Operand, functionalOp, flags, IsPrefix); return res; }
private Expression ReduceCore(DynamicCSharpArgument left) { var functionalOp = new Func<Expression, Expression>(lhs => { var operation = default(ExpressionType); switch (OperationNodeType) { case CSharpExpressionType.AddAssign: case CSharpExpressionType.AddAssignChecked: operation = ExpressionType.AddAssign; break; case CSharpExpressionType.SubtractAssign: case CSharpExpressionType.SubtractAssignChecked: operation = ExpressionType.SubtractAssign; break; case CSharpExpressionType.MultiplyAssign: case CSharpExpressionType.MultiplyAssignChecked: operation = ExpressionType.MultiplyAssign; break; case CSharpExpressionType.DivideAssign: operation = ExpressionType.DivideAssign; break; case CSharpExpressionType.ModuloAssign: operation = ExpressionType.ModuloAssign; break; case CSharpExpressionType.AndAssign: operation = ExpressionType.AndAssign; break; case CSharpExpressionType.OrAssign: operation = ExpressionType.OrAssign; break; case CSharpExpressionType.ExclusiveOrAssign: operation = ExpressionType.ExclusiveOrAssign; break; case CSharpExpressionType.LeftShiftAssign: operation = ExpressionType.LeftShiftAssign; break; case CSharpExpressionType.RightShiftAssign: operation = ExpressionType.RightShiftAssign; break; default: throw ContractUtils.Unreachable; } var args = new[] { CSharpArgumentInfo.Create(GetArgumentInfoFlags(Left), null), CSharpArgumentInfo.Create(GetArgumentInfoFlags(Right), null), }; var binder = Binder.BinaryOperation(Flags, operation, Context, args); var dynamic = DynamicHelpers.MakeDynamic(typeof(object), binder, new[] { lhs, Right.Expression }, new[] { lhs.Type, Right.Expression.Type }); var leftType = Left.Expression.Type; if (leftType != dynamic.Type) { var convert = Binder.Convert(CSharpBinderFlags.ConvertExplicit, leftType, Context); dynamic = DynamicHelpers.MakeDynamic(leftType, convert, new[] { dynamic }, null); } return dynamic; }); var flags = Flags | CSharpBinderFlags.ValueFromCompoundAssignment; var res = DynamicHelpers.ReduceDynamicAssignment(left, functionalOp, flags); return res; }
private Expression WithEventCheck(GetMemberDynamicCSharpExpression member, string accessor) { var obj = member.Object; var name = member.Name; var args = member.Arguments; Debug.Assert(args.Count == 0); var lhs = Expression.Parameter(obj.Type, "__objTemp"); var left = Left.Update(member.Update(lhs, args)); var isEventBinder = Binder.IsEvent(CSharpBinderFlags.None, name, Context); var isEventCheck = DynamicHelpers.MakeDynamic(typeof(bool), isEventBinder, new[] { lhs }, null); var accessorName = accessor + name; var accessorArgs = new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), }; var invokeAccessorBinder = Binder.InvokeMember(CSharpBinderFlags.InvokeSpecialName | CSharpBinderFlags.ResultDiscarded, accessorName, null, Context, accessorArgs); var invokeAccessor = DynamicHelpers.MakeDynamic(typeof(object), invokeAccessorBinder, new[] { lhs, Right.Expression }, null); var ifNotEvent = ReduceCore(left); var res = Expression.Block( new[] { lhs }, Expression.Assign(lhs, obj), Expression.Condition(isEventCheck, invokeAccessor, ifNotEvent) ); return res; }