package com.sun.tools.javac.code;
import static com.sun.tools.javac.code.Flags.STATIC;
import java.util.Iterator;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Substitute.Subst;
import com.sun.tools.javac.code.Substitute.SubstRPLs;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Pair;
/**
* Utility class containing various operations on RPLs.
*
* @author Rob Bocchino
*/
public class RPLs {
protected static final Context.Key<RPLs> rplsKey =
new Context.Key<RPLs>();
final Symtab syms;
public static RPLs instance(Context context) {
RPLs instance = context.get(rplsKey);
if (instance == null)
instance = new RPLs(context);
return instance;
}
protected RPLs(Context context) {
syms = Symtab.instance(context);
}
/** Single, global RPL for Root */
public static final RPL ROOT = new RPL(RPLElement.ROOT_ELEMENT);
/**
* Capture a list of RPLs
*/
public static List<RPL> captureRPLs(List<RPL> list) {
ListBuffer<RPL> lb = ListBuffer.lb();
for (RPL rpl : list) {
RPL captureRPL = rpl.capture();
lb.append(captureRPL);
}
return lb.toList();
}
/**
* Disjoint RPLs. See Section 3.2 of the Tech Report
*/
public boolean areDisjoint(RPL rpl1, RPL rpl2, List<Pair<RPL,RPL>> constraints) {
// If rpl1 and rpl2 are included in disjoint RPLs, then they are disjoint.
for (Pair<RPL,RPL> constraint : constraints) {
if (rpl1.isIncludedIn(constraint.fst) && rpl2.isIncludedIn(constraint.snd))
return true;
if (rpl1.isIncludedIn(constraint.snd) && rpl2.isIncludedIn(constraint.fst))
return true;
}
// DISJOINT-RIGHT-1
if (rpl1.elts.last().isDisjointFrom(rpl2.elts.last(), this,
constraints)) {
return true;
}
// DISJOINT-RIGHT-2
if (areDisjointFromRight(rpl1, rpl2, constraints)) {
return true;
}
// DISJOINT-LEFT
RPL bound1 = rpl1.upperBound();
RPL bound2 = rpl2.upperBound();
if (areDisjointFromLeft(rpl1, rpl2, constraints) ||
areDisjointFromLeft(bound1, bound2, constraints)) {
return true;
}
//System.err.println("Cannot prove that " + rpl1 + " and " + rpl2 + " are disjoint");
return false;
}
public boolean areDisjointFromLeft(RPL rpl1, RPL rpl2,
List<Pair<RPL,RPL>> constraints) {
if (rpl1.isEmpty() && rpl2.isEmpty()) return false;
if (rpl1.isEmpty()) {
for (RPLElement e : rpl2.elts)
if (!e.equals(RPLElement.STAR)) return true;
return false;
}
if (rpl2.isEmpty()) {
for (RPLElement e : rpl1.elts)
if (!e.equals(RPLElement.STAR)) return true;
return false;
}
if (rpl1.isUnderLocal() != rpl2.isUnderLocal())
return true;
// Distinct local names
if (rpl1.elts.head.isDisjointFrom(rpl2.elts.head, this, constraints))
return true;
// Do the RPLs start out the same then diverge?
if (!rpl1.elts.head.equals(rpl2.elts.head)) return false;
List<RPLElement> elts1 = rpl1.elts.tail;
List<RPLElement> elts2 = rpl2.elts.tail;
while (!elts1.isEmpty() || !elts2.isEmpty()) {
if (elts1.head == RPLElement.STAR || elts2.head == RPLElement.STAR)
return false;
if (elts1.isEmpty() || elts2.isEmpty()) return true;
if (elts1.head.isDisjointFrom(elts2.head, this, constraints))
return true;
elts1 = elts1.tail;
elts2 = elts2.tail;
}
return false;
}
public boolean areDisjointFromRight(RPL rpl1, RPL rpl2,
List<Pair<RPL,RPL>> constraints) {
if (rpl1.isEmpty() || rpl2.isEmpty()) return false;
List<RPLElement> elts1 = rpl1.elts.reverse();
List<RPLElement> elts2 = rpl2.elts.reverse();
while (!elts1.isEmpty() && !elts2.isEmpty()) {
if (elts1.head == RPLElement.STAR || elts2.head == RPLElement.STAR)
return false;
if (elts1.head.isDisjointFrom(elts2.head, this, constraints))
return true;
elts1 = elts1.tail;
elts2 = elts2.tail;
}
return false;
}
/**
* Are the region constraints satisfied after subbing actuals for formals?
* @param constraints Constraints that need to be satisfied
* @param formals Formals we are subbing for
* @param actuals Actuals to sub for formals
* @param envConstraints Constraints guaranteed by the environment. For
* example, if we need the constraint P1 # P2,
* and the environment guarantees P1 # P2, that's OK.
* @return Yes or no.
*/
public boolean disjointnessConstraintsAreSatisfied(List<Pair<RPL,RPL>> constraints,
List<RPL> formals, List<RPL> actuals,
List<Pair<RPL,RPL>> envConstraints) {
for (Pair<RPL,RPL> constraint : constraints) {
if (!areDisjoint(constraint.fst.substRPLParams(formals, actuals),
constraint.snd.substRPLParams(formals, actuals),
envConstraints))
return false;
}
return true;
}
/**
* Are regions being consistently bound to parameters, with regard to atomic?
*/
public boolean atomicConstraintsAreSatisfied(List<RPL> formals,
List<RPL> actuals) {
while (formals.nonEmpty() && actuals.nonEmpty()) {
if (formals.head.isAtomic() != actuals.head.isAtomic())
return false;
formals = formals.tail;
actuals = actuals.tail;
}
return true;
}
public List<RPL> substIndices(List<RPL> rpls, List<VarSymbol> from,
List<JCExpression> to) {
ListBuffer<RPL> buf = ListBuffer.<RPL>lb();
for (RPL rpl : rpls) {
buf.append(rpl.substIndices(from, to));
}
return buf.toList();
}
/**
* Substitution classes
*/
public static final Subst substRPLParams = new Subst<RPL,RPL,RPL>() {
public RPL basic(RPL rpl, RPL from, RPL to) {
return rpl.substRPLParam(from, to);
}
};
public static final Subst substTRParams = new Subst<RPL,Type,Type>() {
public RPL basic(RPL rpl, Type from, Type to) {
return rpl.substTRParam(from, to);
}
};
public static final Subst substRPLsForVars = new Subst<RPL,VarSymbol,RPL>() {
public RPL basic(RPL rpl, VarSymbol from, RPL to) {
return rpl.substRPLForVar(from, to);
}
};
public static final Subst substVars = new Subst<RPL,VarSymbol,VarSymbol>() {
public RPL basic(RPL rpl, VarSymbol from, VarSymbol to) {
return rpl.substVar(from, to);
}
};
public static final Subst substExpsForVars =
new Subst<RPL,VarSymbol,JCExpression>() {
public RPL basic(RPL rpl, VarSymbol from, JCExpression to) {
return rpl.substExpForVar(from, to);
}
};
public static final Subst substIndices =
new Subst<RPL,VarSymbol,JCExpression>() {
public RPL basic(RPL rpl, VarSymbol from, JCExpression to) {
return rpl.substIndex(from, to);
}
};
}