package de.skuzzle.polly.core.parser.ast.expressions; import java.util.Arrays; import java.util.List; import de.skuzzle.polly.core.parser.Position; import de.skuzzle.polly.core.parser.ast.ResolvableIdentifier; import de.skuzzle.polly.core.parser.ast.expressions.literals.ProductLiteral; import de.skuzzle.polly.core.parser.ast.lang.Operator; import de.skuzzle.polly.core.parser.ast.lang.Operator.OpType; import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversal; import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversalException; import de.skuzzle.polly.core.parser.ast.visitor.ASTVisitor; import de.skuzzle.polly.core.parser.ast.visitor.Transformation; /** * Represents a call of an operator. OperatorCalls can be created using one of the static * factory methods. * * @author Simon Taddiken */ public class OperatorCall extends Call { /** * Creates a new OperatorCall to a binary expression which has two operands. * * @param position Position of the call within the input. * @param operator The called operator. * @param left The left operand. * @param right The right operand. * @return The created Operator call. */ public final static OperatorCall binary(Position position, OpType operator, Expression left, Expression right) { return new OperatorCall(position, operator, Arrays.asList(new Expression[] {left, right}), false); } /** * Creates a new OperatorCall to a unary expression which has one operand. * * @param position Position of the call within the input. * @param operator The called operator. * @param operand The operand of the operator. * @param postfix Whether this is a postfix operator. If <code>false</code>, this * operator is assumed to be prefix. * @return The created Operator call. */ public final static OperatorCall unary(Position position, OpType operator, Expression operand, boolean postfix) { return new OperatorCall(position, operator, Arrays.asList(new Expression[] {operand}), postfix); } /** * Creates a new OperatorCall to a ternary expression which has three operands. * * @param position Position of the call within the input. * @param operator The called operator. * @param operand1 The first operand. * @param operand2 The second operand. * @param operand3 The third operand. * @return The created Operator call. */ public final static OperatorCall ternary(Position position, OpType operator, Expression operand1, Expression operand2, Expression operand3) { return new OperatorCall(position, operator, Arrays.asList(new Expression[] {operand1, operand2, operand3}), false); } private final OpType operator; private final boolean postfix; /** * Creates a new Operator call. * * @param position Position of the call within the source. * @param operator The called operator. * @param parameters The actual parameters of the call. * @param postfix Whether this is a postfix operator. If <code>false</code>, this * operator is assumed to be prefix (only taken into account for unary * operators.) */ public OperatorCall(Position position, OpType operator, List<Expression> parameters, boolean postfix) { super(position, new VarAccess(position, new ResolvableIdentifier(position, operator.getId())), new ProductLiteral(position, parameters)); this.operator = operator; this.postfix = postfix; } /** * Gets the operator type that is being called. * * @return The operator type. */ public Operator.OpType getOperator() { return this.operator; } /** * For unary operators, returns whether it is a postix or prefix op. For other * operators, the result is undefined but likely to be <code>false</code>. * * @return Whether this is a postfix operator. */ public boolean isPostfix() { return this.postfix; } @Override public boolean visit(ASTVisitor visitor) throws ASTTraversalException { return visitor.visit(this); } @Override public Expression transform(Transformation transformation) throws ASTTraversalException { return transformation.transformOperatorCall(this); } @Override public boolean traverse(ASTTraversal visitor) throws ASTTraversalException { switch (visitor.before(this)) { case ASTTraversal.SKIP: return true; case ASTTraversal.ABORT: return false; } if (!this.getLhs().traverse(visitor)) { return false; } if (!this.getRhs().traverse(visitor)) { return false; } return visitor.after(this) == ASTTraversal.CONTINUE; } @Override public String toString() { return "[OpCall: " + this.operator.getId() + ", type:" + this.getUnique() + "]"; } }