package soottocfg.cfg.statement;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import soottocfg.cfg.SourceLocation;
import soottocfg.cfg.expression.Expression;
import soottocfg.cfg.expression.IdentifierExpression;
import soottocfg.cfg.variable.ClassVariable;
import soottocfg.cfg.variable.Variable;
/**
* @author schaef
* @author rodykers
*
*/
public class PullStatement extends Statement {
private static final long serialVersionUID = 9221818898828469398L;
private final ClassVariable classConstant;
private IdentifierExpression object;
private final List<IdentifierExpression> left;
private final List<Expression> ghostExpressions;
private Set<PushStatement> canAffect;
public PullStatement(SourceLocation loc, ClassVariable c, IdentifierExpression obj,
List<IdentifierExpression> lhs) {
this(loc, c, obj, lhs, null);
}
/**
* @param loc
*/
public PullStatement(SourceLocation loc, ClassVariable c, IdentifierExpression obj,
List<IdentifierExpression> lhs, List<Expression> ghostExp) {
super(loc);
classConstant = c;
object = obj;
left = new LinkedList<IdentifierExpression>(lhs);
this.ghostExpressions = new LinkedList<Expression>();
if (ghostExp!=null) {
this.ghostExpressions.addAll(ghostExp);
}
assert (c.getAssociatedFields().length == left.size());
this.canAffect = new HashSet<PushStatement>();
}
public List<IdentifierExpression> getLeft() {
return left;
}
public List<Expression> getGhostExpressions() {
return this.ghostExpressions;
}
public ClassVariable getClassSignature() {
return classConstant;
}
public Expression getObject() {
return object;
}
@Override
public Set<IdentifierExpression> getUseIdentifierExpressions() {
Set<IdentifierExpression> used = new HashSet<IdentifierExpression>();
used.add(object);
// for (Expression e: ghostExpressions) {
// used.addAll(e.getUseIdentifierExpressions());
// }
return used;
}
@Override
public Set<IdentifierExpression> getDefIdentifierExpressions() {
Set<IdentifierExpression> res = new HashSet<IdentifierExpression>();
res.addAll(left);
for (Expression e: ghostExpressions) {
res.addAll(e.getUseIdentifierExpressions());
}
return res;
}
public Set<PushStatement> getAffectingPushes() {
return canAffect;
}
public void canAffect(PushStatement push) {
canAffect.add(push);
}
public void canAffect(Set<PushStatement> pushes) {
canAffect.addAll(pushes);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
String comma = "";
for (IdentifierExpression v : left) {
sb.append(comma);
sb.append(v);
comma = ", ";
}
sb.append(" := pull(");
sb.append(classConstant.getName());
sb.append(", ");
sb.append(object);
for (Expression e : this.ghostExpressions) {
sb.append(", ");
sb.append(e);
}
sb.append(")");
sb.append("[");
comma = "";
for (PushStatement push : canAffect) {
sb.append(comma);
sb.append(push.getID());
comma = ", ";
}
sb.append("]");
return sb.toString();
}
@Override
public PullStatement deepCopy() {
List<IdentifierExpression> leftCopy = new LinkedList<IdentifierExpression>();
for (IdentifierExpression e : left) {
leftCopy.add(e.deepCopy());
}
List<Expression> ghostCopy = new LinkedList<Expression>();
for (Expression e : ghostExpressions) {
ghostCopy.add(e.deepCopy());
}
return new PullStatement(getSourceLocation(), classConstant, object.deepCopy(), leftCopy, ghostCopy);
}
@Override
public PullStatement substitute(Map<Variable, Variable> subs) {
List<IdentifierExpression> leftCopy = new LinkedList<IdentifierExpression>();
for (IdentifierExpression e : left) {
leftCopy.add(e.substitute(subs));
}
List<Expression> ghostCopy = new LinkedList<Expression>();
for (Expression e : ghostExpressions) {
ghostCopy.add(e.substitute(subs));
}
return new PullStatement(getSourceLocation(), classConstant, object.substitute(subs), leftCopy, ghostCopy);
}
@Override
public PullStatement substituteVarWithExpression(Map<Variable, Expression> subs) {
List<IdentifierExpression> leftCopy = new LinkedList<IdentifierExpression>();
for (IdentifierExpression e : left) {
leftCopy.add(e.deepCopy());
}
List<Expression> ghostCopy = new LinkedList<Expression>();
for (Expression e : ghostExpressions) {
ghostCopy.add(e.substituteVarWithExpression(subs));
}
// Verify.verify(!subs.containsKey(object.getVariable()));
return new PullStatement(getSourceLocation(), classConstant, object.deepCopy(), leftCopy, ghostCopy);
}
}