Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* UnaryExpression.java
*
* Copyright (c) 2012 Mike Strobel
*
* This source code is based on the Dynamic Language Runtime from Microsoft,
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.expressions;
import com.strobel.reflection.MethodInfo;
import com.strobel.reflection.Type;
/**
* Represents an expression that has a unary operator.
* @author Mike Strobel
*/
public final class UnaryExpression extends Expression {
private final Expression _operand;
private final MethodInfo _method;
private final ExpressionType _nodeType;
private final Type _type;
UnaryExpression(final ExpressionType nodeType, final Expression operand, final Type type, final MethodInfo method) {
_nodeType = nodeType;
_operand = operand;
_type = type;
_method = method;
}
/**
* Gets the implementing method for the unary operation.
* @return an {@link Expression} that represents the operand of the unary operation.
*/
public final Expression getOperand() {
return _operand;
}
/**
* Gets the implementing method for the unary operation.
* @return the {@link MethodInfo} that represents the implementing method.
*/
public final MethodInfo getMethod() {
return _method;
}
@Override
public final Type> getType() {
return _type;
}
@Override
public final ExpressionType getNodeType() {
return _nodeType;
}
@Override
protected final Expression accept(final ExpressionVisitor visitor) {
return visitor.visitUnary(this);
}
@Override
public final boolean canReduce() {
switch (_nodeType) {
case PreIncrementAssign:
case PreDecrementAssign:
case PostIncrementAssign:
case PostDecrementAssign:
return true;
}
return false;
}
@Override
public final Expression reduce() {
if (canReduce()) {
switch (_operand.getNodeType()) {
case MemberAccess:
return reduceMember();
default:
return reduceVariable();
}
}
return this;
}
private Expression reduceVariable() {
if (isPrefix()) {
// (op) var => var = op(var)
return assign(_operand, functionalOp(_operand));
}
// var (op) => temp = var; var = op(var); temp
final ParameterExpression temp = parameter(_operand.getType());
return block(
_type,
new ParameterExpression[] { temp },
assign(temp, _operand),
assign(_operand, functionalOp(temp)),
temp
);
}
private Expression reduceMember() {
MemberExpression member = (MemberExpression)_operand;
if (member.getTarget() == null) {
// Static member; reduce the same as variable.
return reduceVariable();
}
else {
final ParameterExpression temp1 = parameter(member.getTarget().getType(), null);
final Expression initTemp1 = assign(temp1, member.getTarget());
member = makeMemberAccess(temp1, member.getMember());
if (isPrefix()) {
// (op) value.member => temp1 = value; temp1.member = op(temp1.member)
return block(
new ParameterExpression[]{temp1},
initTemp1,
assign(member, functionalOp(member))
);
}
// value.member (op) => temp1 = value; temp2 = temp1.member; temp1.member = op(temp2); temp2
final ParameterExpression temp2 = parameter(member.getType(), null);
return block(
new ParameterExpression[]{temp1, temp2},
initTemp1,
assign(temp2, member),
assign(member, functionalOp(temp2)),
temp2
);
}
}
private boolean isPrefix() {
return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign;
}
private UnaryExpression functionalOp(final Expression operand) {
final ExpressionType functional;
if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
functional = ExpressionType.Increment;
}
else {
functional = ExpressionType.Decrement;
}
return new UnaryExpression(functional, operand, operand.getType(), _method);
}
public final UnaryExpression update(final Expression operand) {
if (operand == _operand) {
return this;
}
return makeUnary(_nodeType, operand, _type, _method);
}
}