LoopLocation.java
package edu.udel.cis.vsl.tass.model.impl.location;
import java.util.Collection;
import java.util.LinkedHashSet;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.model.IF.expression.BinaryExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.LHSExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.UnaryExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.VariableExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF.ExpressionKind;
import edu.udel.cis.vsl.tass.model.IF.location.AssignmentLocationIF;
import edu.udel.cis.vsl.tass.model.IF.location.InvocationLocationIF;
import edu.udel.cis.vsl.tass.model.IF.location.LocationIF;
import edu.udel.cis.vsl.tass.model.IF.location.LoopLocationIF;
import edu.udel.cis.vsl.tass.model.IF.location.ReceiveLocationIF;
import edu.udel.cis.vsl.tass.model.IF.scope.LocalScopeIF;
import edu.udel.cis.vsl.tass.model.IF.statement.ReceiveStatementIF;
import edu.udel.cis.vsl.tass.model.IF.statement.StatementIF;
import edu.udel.cis.vsl.tass.model.IF.variable.VariableIF;
public class LoopLocation extends BinaryChoiceLocation implements
LoopLocationIF {
private Collection<VariableIF> writevars = null;
private Collection<VariableIF> writerefs = null;
private Collection<LocationIF> body = null;
public LoopLocation(LocalScopeIF scope, ExpressionIF condition) {
super(scope, condition);
}
@Override
public Collection<LocationIF> body() {
if (!isComplete()) {
throw new RuntimeException(
"Must complete model before calling body");
}
return body;
}
/**
* Experimental method: returns reference variables that are written to in
* the loop body.
*/
public Collection<VariableIF> writerefs() {
if (!isComplete()) {
throw new RuntimeException(
"Must complete model before calling writerefs");
}
return writerefs;
}
/**
* Experimental method: returns non-reference variables that are written to
* in the loop body.
*/
public Collection<VariableIF> writevars() {
if (!isComplete()) {
throw new RuntimeException(
"Must complete model before calling writevars");
}
return writevars;
}
private VariableIF baseArray(ExpressionIF arrayExpression)
throws SyntaxException {
if (arrayExpression.kind() == ExpressionKind.SUBSCRIPT)
return baseArray(((BinaryExpressionIF) arrayExpression).left());
if (arrayExpression.kind() == ExpressionKind.VARIABLE)
return ((VariableExpressionIF) arrayExpression).variable();
return null;
}
private void processLHS(LHSExpressionIF lhs) throws SyntaxException {
if (lhs.kind() == ExpressionKind.VARIABLE) {
writevars.add(((VariableExpressionIF) lhs).variable());
} else if (lhs.kind() == ExpressionKind.SUBSCRIPT) {
VariableIF variable = baseArray(lhs);
if (variable != null)
writerefs.add(variable);
}
}
private void computeWrites() throws SyntaxException {
writevars = new LinkedHashSet<VariableIF>();
writerefs = new LinkedHashSet<VariableIF>();
for (LocationIF location : body) {
if (location.kind() == LocationKind.ASSIGNMENT) {
processLHS(((AssignmentLocationIF) location).statement().lhs());
} else if (location.kind() == LocationKind.INVOCATION) {
LHSExpressionIF lhs = ((InvocationLocationIF) location)
.statement().lhs();
if (lhs != null)
processLHS(lhs);
} else if (location.kind() == LocationKind.RECEIVE) {
ReceiveLocationIF receiveLocation = (ReceiveLocationIF) location;
for (StatementIF statement : receiveLocation.statements()) {
ReceiveStatementIF receiveStatement = (ReceiveStatementIF) statement;
processLHS(receiveStatement.buffer());
if (receiveStatement.tag().kind() == ExpressionKind.ANY) {
processLHS((LHSExpressionIF) (((UnaryExpressionIF) receiveStatement
.tag()).expression()));
}
}
}
}
}
private void dfs(LocationIF location) {
if (body.contains(location))
return;
body.add(location);
for (StatementIF statement : location.statements()) {
if (!statement.equals(falseBranch))
dfs(statement.targetLocation());
}
}
/**
* To compute the body of the loop, find all nodes reachable from this node
* without passing through the false branch. Include this node in the body.
* Then check that for any edge e leading to a body node other than this
* node, the source location of e is in the body. Then check that for any
* edge e leading from a body node, the destination is either in the body or
* is the exit node.
*/
@Override
public void complete() throws SyntaxException {
LocationIF exitNode = falseBranch.targetLocation();
body = new LinkedHashSet<LocationIF>();
dfs(this);
for (LocationIF location : body) {
if (!this.equals(location)) {
for (StatementIF statement : location.incomingStatements()) {
LocationIF source = statement.sourceLocation();
if (!body.contains(source)) {
throw new SyntaxException(statement, "Statement from "
+ source + " to " + location
+ " enters body of loop " + this);
}
}
}
for (StatementIF statement : location.statements()) {
LocationIF target = statement.targetLocation();
if (!exitNode.equals(target) && !body.contains(target)) {
throw new SyntaxException(statement, "Statement from "
+ location + " to " + target + " escapes loop body");
}
}
}
computeWrites();
super.complete();
}
}