package soottocfg.cfg.optimization;
import java.util.LinkedList;
import java.util.List;
import com.google.common.base.Verify;
import soottocfg.cfg.expression.BinaryExpression;
import soottocfg.cfg.expression.Expression;
import soottocfg.cfg.expression.IdentifierExpression;
import soottocfg.cfg.expression.IteExpression;
import soottocfg.cfg.expression.TupleAccessExpression;
import soottocfg.cfg.expression.UnaryExpression;
import soottocfg.cfg.expression.literal.BooleanLiteral;
import soottocfg.cfg.expression.literal.IntegerLiteral;
import soottocfg.cfg.expression.literal.NullLiteral;
import soottocfg.cfg.method.CfgBlock;
import soottocfg.cfg.method.CfgEdge;
import soottocfg.cfg.method.Method;
import soottocfg.cfg.statement.AssertStatement;
import soottocfg.cfg.statement.AssignStatement;
import soottocfg.cfg.statement.AssumeStatement;
import soottocfg.cfg.statement.CallStatement;
import soottocfg.cfg.statement.NewStatement;
import soottocfg.cfg.statement.PullStatement;
import soottocfg.cfg.statement.PushStatement;
import soottocfg.cfg.statement.Statement;
import soottocfg.cfg.util.CfgVisitor;
//DSN should this be an abstract class
//DSN There might be value in tracking whether an expression actually changed. Possible optimization
public class CfgUpdater extends CfgVisitor {
protected Boolean changed = false;
public boolean updateMethod(Method m) {
changed = false;
processMethod(m);
return changed;
}
public boolean runFixpt(Method m) {
boolean everChanged = false;
while (updateMethod(m)) {
everChanged = true;
}
return everChanged;
}
public CfgUpdater() {
}
@Override
protected void processCfgBlock(CfgBlock block) {
setCurrentCfgBlock(block);
// We need to update the statements
block.setStatements(processStatementList(block.getStatements()));
// and also the graph conditions, in case those have been changed by the
// analysis
for (CfgEdge edge : block.getMethod().outgoingEdgesOf(block)) {
if (edge.getLabel().isPresent()) {
edge.setLabel(processExpression(edge.getLabel().get()));
}
}
setCurrentCfgBlock(null);
}
@Override
protected List<Statement> processStatementList(List<Statement> sl) {
List<Statement> rval = new LinkedList<Statement>();
for (Statement s : sl) {
rval.add(processStatement(s));
}
return rval;
}
@Override
protected Statement processStatement(AssertStatement s) {
Expression e = processExpression(s.getExpression());
return new AssertStatement(s.getSourceLocation(), e);
}
@Override
protected Statement processStatement(PullStatement s) {
List<IdentifierExpression> lhs = new LinkedList<IdentifierExpression>();
for (IdentifierExpression l : s.getLeft()) {
lhs.add((IdentifierExpression)processExpression(l));
}
IdentifierExpression obj = (IdentifierExpression) processExpression(s.getObject());
return new PullStatement(s.getSourceLocation(), s.getClassSignature(), obj, lhs);
}
@Override
protected Statement processStatement(PushStatement s) {
List<Expression> rhs = new LinkedList<Expression>();
for (Expression r : s.getRight()) {
rhs.add(processExpression(r));
}
IdentifierExpression obj = (IdentifierExpression) processExpression(s.getObject());
return new PushStatement(s.getSourceLocation(), s.getClassSignature(), obj, rhs);
}
@Override
protected Statement processStatement(AssignStatement s) {
Expression lhs = processExpression(s.getLeft());
Expression rhs = processExpression(s.getRight());
return new AssignStatement(s.getSourceLocation(), lhs, rhs);
}
@Override
protected Statement processStatement(AssumeStatement s) {
Expression e = processExpression(s.getExpression());
return new AssumeStatement(s.getSourceLocation(), e);
}
@Override
protected Statement processStatement(CallStatement s) {
List<Expression> args = processExpressionList(s.getArguments());
List<Expression> rec = new LinkedList<Expression>();
for (Expression e : s.getReceiver()) {
rec.add(processExpression(e));
}
return new CallStatement(s.getSourceLocation(), s.getCallTarget(), args, rec);
}
@Override
protected Statement processStatement(NewStatement s) {
Expression e = processExpression(s.getLeft());
Verify.verify(e instanceof IdentifierExpression);
return new NewStatement(s.getSourceLocation(), (IdentifierExpression) e, s.getClassVariable());
}
/// Expressions
@Override
protected List<Expression> processExpressionList(List<Expression> el) {
List<Expression> rval = new LinkedList<Expression>();
for (Expression e : el) {
rval.add(processExpression(e));
}
return rval;
}
@Override
protected Expression processExpression(BinaryExpression e) {
Expression left = processExpression(e.getLeft());
Expression right = processExpression(e.getRight());
return new BinaryExpression(e.getSourceLocation(), e.getOp(), left, right);
}
@Override
protected Expression processExpression(BooleanLiteral e) {
return e.deepCopy();
}
@Override
protected Expression processExpression(NullLiteral e) {
return e.deepCopy();
}
@Override
protected Expression processExpression(IdentifierExpression e) {
return e.deepCopy();
}
@Override
protected Expression processExpression(IntegerLiteral e) {
return e.deepCopy();
}
@Override
protected Expression processExpression(TupleAccessExpression e) {
return e.deepCopy();
}
@Override
protected Expression processExpression(IteExpression ite) {
Expression i = processExpression(ite.getCondition());
Expression t = processExpression(ite.getThenExpr());
Expression e = processExpression(ite.getElseExpr());
return new IteExpression(ite.getSourceLocation(), i, t, e);
}
@Override
protected Expression processExpression(UnaryExpression e) {
Expression exp = processExpression(e.getExpression());
return new UnaryExpression(e.getSourceLocation(), e.getOp(), exp);
}
}