boomerang.results.AbstractBoomerangResults Maven / Gradle / Ivy
package boomerang.results;
import boomerang.ForwardQuery;
import boomerang.scene.ControlFlowGraph.Edge;
import boomerang.scene.Statement;
import boomerang.scene.Val;
import boomerang.solver.AbstractBoomerangSolver;
import boomerang.solver.ForwardBoomerangSolver;
import boomerang.util.DefaultValueMap;
import com.google.common.collect.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sync.pds.solver.nodes.GeneratedState;
import sync.pds.solver.nodes.INode;
import sync.pds.solver.nodes.Node;
import sync.pds.solver.nodes.SingleNode;
import wpds.impl.PAutomaton;
import wpds.impl.Transition;
import wpds.impl.Weight;
import wpds.impl.WeightedPAutomaton;
import wpds.interfaces.WPAStateListener;
public class AbstractBoomerangResults {
protected final DefaultValueMap> queryToSolvers;
protected final Logger LOGGER = LoggerFactory.getLogger(AbstractBoomerangResults.class);
public AbstractBoomerangResults(
DefaultValueMap> solverMap) {
this.queryToSolvers = solverMap;
}
protected Context constructContextGraph(ForwardQuery forwardQuery, Node targetFact) {
Context context = new Context(targetFact, forwardQuery);
AbstractBoomerangSolver forwardSolver = queryToSolvers.get(forwardQuery);
computeUnmatchedOpeningContext(context, forwardSolver, targetFact);
computeUnmatchedClosingContext(context, forwardSolver);
return context;
}
public void computeUnmatchedClosingContext(
Context context, AbstractBoomerangSolver forwardSolver) {
for (Transition> t : forwardSolver.getCallAutomaton().getTransitions()) {
if (t.getTarget().fact().isUnbalanced()) {
INode v = t.getTarget();
forwardSolver
.getCallAutomaton()
.registerListener(new ClosingCallStackExtracter<>(v, v, context, forwardSolver));
}
}
}
public void computeUnmatchedOpeningContext(
Context context, AbstractBoomerangSolver forwardSolver, Node node) {
SingleNode initialState = new SingleNode<>(node.fact());
forwardSolver
.getCallAutomaton()
.registerListener(
new OpeningCallStackExtracter<>(initialState, initialState, context, forwardSolver));
}
public Table asStatementValWeightTable(ForwardQuery query) {
return queryToSolvers.getOrCreate(query).asStatementValWeightTable();
}
private static class OpeningCallStackExtracter
extends WPAStateListener, W> {
private AbstractBoomerangSolver solver;
private INode source;
private Context context;
public OpeningCallStackExtracter(
INode state, INode source, Context context, AbstractBoomerangSolver solver) {
super(state);
this.source = source;
this.context = context;
this.solver = solver;
}
@Override
public void onOutTransitionAdded(
Transition> t,
W w,
WeightedPAutomaton, W> weightedPAutomaton) {
if (weightedPAutomaton.getInitialStates().contains(t.getTarget())) {
return;
}
// TODO Doesn't work anymore!
if (t.getLabel().getMethod() != null) {
if (t.getStart() instanceof GeneratedState) {
context
.getOpeningContext()
.addTransition(new Transition<>(source, t.getLabel(), t.getTarget()));
} else {
weightedPAutomaton.registerListener(
new OpeningCallStackExtracter<>(t.getTarget(), source, context, solver));
return;
}
}
weightedPAutomaton.registerListener(
new OpeningCallStackExtracter<>(t.getTarget(), t.getTarget(), context, solver));
}
@Override
public void onInTransitionAdded(
Transition> t,
W w,
WeightedPAutomaton, W> weightedPAutomaton) {}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((context == null) ? 0 : context.hashCode());
result = prime * result + ((solver == null) ? 0 : solver.hashCode());
result = prime * result + ((source == null) ? 0 : source.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!super.equals(obj)) return false;
if (getClass() != obj.getClass()) return false;
OpeningCallStackExtracter other = (OpeningCallStackExtracter) obj;
if (context == null) {
if (other.context != null) return false;
} else if (!context.equals(other.context)) return false;
if (solver == null) {
if (other.solver != null) return false;
} else if (!solver.equals(other.solver)) return false;
if (source == null) {
if (other.source != null) return false;
} else if (!source.equals(other.source)) return false;
return true;
}
}
private static class ClosingCallStackExtracter
extends WPAStateListener, W> {
private AbstractBoomerangSolver solver;
private INode source;
private Context context;
public ClosingCallStackExtracter(
INode state, INode source, Context context, AbstractBoomerangSolver solver) {
super(state);
this.source = source;
this.context = context;
this.solver = solver;
}
@Override
public void onOutTransitionAdded(
Transition> t,
W w,
WeightedPAutomaton, W> weightedPAutomaton) {}
@Override
public void onInTransitionAdded(
Transition> t,
W w,
WeightedPAutomaton, W> weightedPAutomaton) {
if (weightedPAutomaton.isUnbalancedState(t.getStart())) {
if (!t.getStart().fact().isStatic()) {
context.getClosingContext().addTransition(t);
}
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((context == null) ? 0 : context.hashCode());
result = prime * result + ((solver == null) ? 0 : solver.hashCode());
result = prime * result + ((source == null) ? 0 : source.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!super.equals(obj)) return false;
if (getClass() != obj.getClass()) return false;
ClosingCallStackExtracter other = (ClosingCallStackExtracter) obj;
if (context == null) {
if (other.context != null) return false;
} else if (!context.equals(other.context)) return false;
if (solver == null) {
if (other.solver != null) return false;
} else if (!solver.equals(other.solver)) return false;
if (source == null) {
if (other.source != null) return false;
} else if (!source.equals(other.source)) return false;
return true;
}
}
public static class Context {
final Node node;
private final PAutomaton> openingContext;
private final PAutomaton> closingContext;
public Context(Node node, ForwardQuery forwardQuery) {
this.node = node;
this.openingContext =
new PAutomaton>() {
@Override
public INode createState(INode d, Edge loc) {
throw new RuntimeException("Not implemented");
}
@Override
public boolean isGeneratedState(INode d) {
throw new RuntimeException("Not implemented");
}
@Override
public Edge epsilon() {
return new Edge(Statement.epsilon(), Statement.epsilon());
}
};
this.closingContext =
new PAutomaton>() {
@Override
public INode createState(INode d, Edge loc) {
throw new RuntimeException("Not implemented");
}
@Override
public boolean isGeneratedState(INode d) {
throw new RuntimeException("Not implemented");
}
@Override
public Edge epsilon() {
return new Edge(Statement.epsilon(), Statement.epsilon());
}
};
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((closingContext == null) ? 0 : closingContext.hashCode());
result = prime * result + ((node == null) ? 0 : node.hashCode());
result = prime * result + ((openingContext == null) ? 0 : openingContext.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Context other = (Context) obj;
if (node == null) {
if (other.node != null) return false;
} else if (!node.equals(other.node)) return false;
return true;
}
public PAutomaton> getOpeningContext() {
return openingContext;
}
public PAutomaton> getClosingContext() {
return closingContext;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy