package org.jmlspecs.openjml.esc;
import org.jmlspecs.openjml.JmlTreeScanner;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCAssignOp;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCUnary;
import com.sun.tools.javac.util.ListBuffer;
/** This class is a tree walker that finds everything that is the target of
* a modification in the tree being walked: assignments, assignment-ops,
* increment and decrement operators, fields specified as modified by a
* method call.
*/
// FIXME - is the tree already in reduced BasicBlock form?
public class TargetFinder extends JmlTreeScanner {
private ListBuffer<JCExpression> vars;
public TargetFinder() {}
/** Finds variables in the given JCTree, adding them to the list that is the
* second argument; the second argument is returned.
*/
public static /*@Nullable*/ListBuffer<JCExpression> findVars(JCTree that, /*@Nullable*/ListBuffer<JCExpression> v) {
if (that == null) return v;
TargetFinder vf = new TargetFinder();
return vf.find(that,v);
}
/** Finds variables in the given JCTrees, adding them to the list that is the
* second argument; the second argument is returned.
*/
public static ListBuffer<JCExpression> findVars(Iterable<? extends JCTree> list, /*@Nullable*/ListBuffer<JCExpression> v) {
TargetFinder vf = new TargetFinder();
return vf.find(list,v);
}
/** Finds variables in the given JCTrees, adding them to the list that is the
* second argument; the second argument is returned.
*/
public ListBuffer<JCExpression> find(Iterable<? extends JCTree> list, /*@Nullable*/ListBuffer<JCExpression> v) {
if (v == null) vars = new ListBuffer<JCExpression>();
else vars = v;
for (JCTree t: list) t.accept(this);
return vars;
}
/** Finds variables in the given JCTrees, adding them to the list that is the
* second argument; the second argument is returned.
*/
public ListBuffer<JCExpression> find(JCTree that, ListBuffer<JCExpression> v) {
if (that == null) return v;
if (v == null) vars = new ListBuffer<JCExpression>();
else vars = v;
that.accept(this);
return vars;
}
@Override
public void visitAssign(JCAssign that) {
vars.add(that.lhs);
}
@Override
public void visitAssignop(JCAssignOp that) {
vars.add(that.lhs);
}
@Override
public void visitUnary(JCUnary that) {
JCTree.Tag op = that.getTag();
if (op == JCTree.Tag.POSTDEC || op == JCTree.Tag.POSTINC ||
op == JCTree.Tag.PREINC || op == JCTree.Tag.PREDEC)
vars.add(that.getExpression());
}
// FIXME - also need targets of method calls, update statements of loops,
// initialization statements of loops, specs of method calls
}