package de.gaalop.cfg;
import de.gaalop.dfg.Expression;
import de.gaalop.dfg.Variable;
public class LoopNode extends SequentialNode {
private SequentialNode body;
private int iterations;
private Variable counter;
public LoopNode(ControlFlowGraph graph) {
super(graph);
}
/**
* Sets the number of iterations. This can either be specified in advance, e.g. by a pragma value in the input code
* or determined at runtime, e.g. by inspecting the loop body.
*
* @param iterations number of iterations, e.g. for unrolling
*/
public void setIterations(int iterations) {
this.iterations = iterations;
}
/**
* Returns the number of iterations. This can be used to unroll the loop, for instance.
*
* @return number of iterations
*/
public int getIterations() {
return iterations;
}
public void setCounterVariable(Variable counter) {
this.counter = counter;
}
public Variable getCounterVariable() {
return counter;
}
public void setBody(SequentialNode body) {
this.body = body;
}
public SequentialNode getBody() {
return body;
}
@Override
public void replaceExpression(Expression old, Expression newExpression) {
replaceSubtree(body, old, newExpression);
}
private void replaceSubtree(Node root, Expression old, Expression newExpression) {
if (root instanceof BlockEndNode || root instanceof EndNode) {
return;
} else if (root instanceof SequentialNode) {
root.replaceExpression(old, newExpression);
replaceSubtree(((SequentialNode) root).getSuccessor(), old, newExpression);
}
}
@Override
public void replaceSuccessor(Node oldSuccessor, Node newSuccessor) {
if (oldSuccessor == body) {
newSuccessor.removePredecessor(oldSuccessor);
newSuccessor.addPredecessor(this);
body = (SequentialNode) newSuccessor;
} else {
super.replaceSuccessor(oldSuccessor, newSuccessor);
}
}
@Override
public void accept(ControlFlowVisitor visitor) {
visitor.visit(this);
}
@Override
public LoopNode copyElements() {
LoopNode copy = new LoopNode(getGraph());
copy.setIterations(iterations);
copy.setCounterVariable(counter);
SequentialNode newBody = body.copy();
newBody.removePredecessor(this);
newBody.addPredecessor(copy);
copy.setBody(newBody);
copySubtree(newBody, copy);
return copy;
}
private void copySubtree(SequentialNode root, SequentialNode newBase) {
if (root instanceof BlockEndNode) {
((BlockEndNode) root).updateBase(newBase);
return;
} else if (root.getSuccessor() instanceof SequentialNode) {
SequentialNode successor = (SequentialNode) root.getSuccessor();
SequentialNode newSuccessor = successor.copy();
root.replaceSuccessor(successor, newSuccessor);
copySubtree(newSuccessor, newBase);
}
}
@Override
public String toString() {
return "loop { " + body + " ... }";
}
}