CommonOperatorNode.java
package edu.udel.cis.vsl.abc.ast.node.common.expression;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.List;
import edu.udel.cis.vsl.abc.ast.IF.ASTException;
import edu.udel.cis.vsl.abc.ast.IF.DifferenceObject;
import edu.udel.cis.vsl.abc.ast.conversion.IF.Conversion;
import edu.udel.cis.vsl.abc.ast.node.IF.ASTNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.ExpressionNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.OperatorNode;
import edu.udel.cis.vsl.abc.ast.type.IF.Type;
import edu.udel.cis.vsl.abc.ast.type.IF.Type.TypeKind;
import edu.udel.cis.vsl.abc.token.IF.Source;
public class CommonOperatorNode extends CommonExpressionNode
implements
OperatorNode {
private Operator operator;
public CommonOperatorNode(Source source, Operator operator,
List<ExpressionNode> arguments) {
super(source, arguments);
this.operator = operator;
}
@Override
public Operator getOperator() {
return operator;
}
@Override
public void setOperator(Operator operator) {
this.operator = operator;
}
@Override
public int getNumberOfArguments() {
return this.numChildren();
}
@Override
public ExpressionNode getArgument(int index) {
return (ExpressionNode) child(index);
}
@Override
public void setArgument(int index, ExpressionNode value) {
setChild(index, value);
}
@Override
protected void printBody(PrintStream out) {
out.print("OperatorNode[operator=" + operator + "]");
}
private boolean hasConstantOperator() {
switch (operator) {
case ASSIGN :
case BITANDEQ :
case BITOREQ :
case BITXOREQ :
case DIVEQ :
case MINUSEQ :
case MODEQ :
case PLUSEQ :
case POSTDECREMENT :
case POSTINCREMENT :
case PREDECREMENT :
case PREINCREMENT :
case SHIFTLEFTEQ :
case SHIFTRIGHTEQ :
case TIMESEQ :
return false;
default :
return true;
}
}
@Override
public boolean isConstantExpression() {
int numArgs = getNumberOfArguments();
if (!hasConstantOperator())
return false;
for (int i = 0; i < numArgs; i++) {
if (!getArgument(i).isConstantExpression())
return false;
}
return true;
}
@Override
public OperatorNode copy() {
List<ExpressionNode> arguments = new LinkedList<ExpressionNode>();
int numArgs = getNumberOfArguments();
for (int i = 0; i < numArgs; i++)
arguments.add(duplicate(getArgument(i)));
return new CommonOperatorNode(getSource(), getOperator(), arguments);
}
@Override
public ExpressionKind expressionKind() {
return ExpressionKind.OPERATOR;
}
@Override
public boolean isSideEffectFree(boolean errorsAreSideEffects) {
switch (getOperator()) {
// always have side effects:
case ASSIGN :
case MINUSEQ :
case PLUSEQ :
case POSTDECREMENT :
case POSTINCREMENT :
case PREDECREMENT :
case PREINCREMENT :
case DIVEQ :
case MODEQ :
case TIMESEQ :
case BITANDEQ :
case BITOREQ :
case BITXOREQ :
case SHIFTLEFTEQ :
case SHIFTRIGHTEQ :
return false;
// possible numeric arithmetic error only:
case DIV :
case MOD :
case TIMES :
case UNARYMINUS :
if (errorsAreSideEffects) {
// perhaps check if expressions are constants that are not
// 0,
// for example. But overflow could also be a problem.
return false;
}
break;
// possible pointer or numeric arithmetic error:
case MINUS :
case PLUS :
// If the PLUS or MINUS is part of the pointer addition
// operation, then it may have error side-effects. Else, it is
// numerical operation which will not have error side-effects:
if (errorsAreSideEffects)
if (getArgument(0).getType().kind() == TypeKind.POINTER
|| getArgument(1).getType()
.kind() == TypeKind.POINTER)
return false;
break;
// always a problem:
case DEREFERENCE :
case SUBSCRIPT :
if (errorsAreSideEffects) {
return false;
}
break;
// innocuous unless operands have side effects...
case ADDRESSOF :
case BIG_O :
case BITAND :
case BITCOMPLEMENT :
case BITOR :
case BITXOR :
case COMMA :
case CONDITIONAL :
case EQUALS :
case GT :
case GTE :
case IMPLIES :
case LAND :
case LOR :
case LT :
case LTE :
case NEQ :
case NOT :
case SHIFTLEFT :
case SHIFTRIGHT :
case UNARYPLUS :
case HASH :
break;
default :
break;
} // end of switch
// default case: check operands...
for (int i = 0; i < getNumberOfArguments(); i++) {
if (!getArgument(i).isSideEffectFree(errorsAreSideEffects))
return false;
}
return true;
}
@Override
protected DifferenceObject diffWork(ASTNode that) {
if (that instanceof OperatorNode)
if (this.operator == ((OperatorNode) that).getOperator())
return null;
return new DifferenceObject(this, that);
}
@Override
public ASTNode setChild(int index, ASTNode child) {
if (!(child == null || child instanceof ExpressionNode))
throw new ASTException("Child of CommonOperatorNode at index "
+ index + " must be a ExpressionNode, but saw " + child
+ " with type " + child.nodeKind());
return super.setChild(index, child);
}
@Override
public void addConversion(Conversion conversion) {
Type lastType = getConvertedType();
if (lastType == null)
throw new RuntimeException(
"Internal error: adding conversion before initial type defined");
if (!lastType.equals(conversion.getOldType()))
throw new IllegalArgumentException(
"Old type of conversion is not last type:\n"
+ conversion.getOldType() + "\n" + lastType);
conversions.add(conversion);
if (operator == Operator.CONDITIONAL) {
ExpressionNode truBrh = getArgument(1);
ExpressionNode flsBrh = getArgument(2);
truBrh.addConversion(conversion);
flsBrh.addConversion(conversion);
}
}
}