org.checkerframework.dataflow.reachingdef.ReachingDefinitionStore Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dataflow Show documentation
Show all versions of dataflow Show documentation
Dataflow is a dataflow framework based on the javac compiler.
package org.checkerframework.dataflow.reachingdef;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.visualize.CFGVisualizer;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.javacutil.BugInCF;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.StringJoiner;
/**
* A reaching definition store contains a set of reaching definitions represented by
* ReachingDefinitionNode
*/
public class ReachingDefinitionStore implements Store {
/** The set of reaching definitions in this store */
private final Set reachingDefSet;
/** Create a new ReachDefinitionStore. */
public ReachingDefinitionStore() {
reachingDefSet = new LinkedHashSet<>();
}
/**
* Create a new ReachDefinitionStore.
*
* @param reachingDefSet a set of reaching definition nodes. The parameter is captured and the
* caller should not retain an alias.
*/
public ReachingDefinitionStore(Set reachingDefSet) {
this.reachingDefSet = reachingDefSet;
}
/**
* Remove the information of a reaching definition from the reaching definition set.
*
* @param defTarget target of a reaching definition
*/
public void killDef(Node defTarget) {
Iterator it = reachingDefSet.iterator();
while (it.hasNext()) {
// We use `.equals` instead of `==` here to compare value equality
// rather than reference equality, because if two left-hand side node
// have same values, we need to kill the old one and replace with the
// new one.
ReachingDefinitionNode generatedDefNode = it.next();
if (generatedDefNode.def.getTarget().equals(defTarget)) {
it.remove();
}
}
}
/**
* Add a reaching definition to the reaching definition set.
*
* @param def a reaching definition
*/
public void putDef(ReachingDefinitionNode def) {
reachingDefSet.add(def);
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof ReachingDefinitionStore)) {
return false;
}
ReachingDefinitionStore other = (ReachingDefinitionStore) obj;
return other.reachingDefSet.equals(this.reachingDefSet);
}
@Override
public int hashCode() {
return this.reachingDefSet.hashCode();
}
@Override
public ReachingDefinitionStore copy() {
return new ReachingDefinitionStore(new LinkedHashSet<>(reachingDefSet));
}
@Override
public ReachingDefinitionStore leastUpperBound(ReachingDefinitionStore other) {
LinkedHashSet reachingDefSetLub =
new LinkedHashSet<>(this.reachingDefSet.size() + other.reachingDefSet.size());
reachingDefSetLub.addAll(this.reachingDefSet);
reachingDefSetLub.addAll(other.reachingDefSet);
return new ReachingDefinitionStore(reachingDefSetLub);
}
@Override
public ReachingDefinitionStore widenedUpperBound(ReachingDefinitionStore previous) {
throw new BugInCF("ReachingDefinitionStore.widenedUpperBound was called!");
}
@Override
public boolean canAlias(JavaExpression a, JavaExpression b) {
return true;
}
@Override
public String visualize(CFGVisualizer, ReachingDefinitionStore, ?> viz) {
String key = "reaching definitions";
if (reachingDefSet.isEmpty()) {
return viz.visualizeStoreKeyVal(key, "none");
}
StringJoiner sjStoreVal = new StringJoiner(", ", "{ ", " }");
for (ReachingDefinitionNode reachDefNode : reachingDefSet) {
sjStoreVal.add(reachDefNode.toString());
}
return viz.visualizeStoreKeyVal(key, sjStoreVal.toString());
}
@Override
public String toString() {
return "ReachingDefinitionStore: " + reachingDefSet.toString();
}
}