Search in sources :

Example 1 with DirectedGraph

use of edu.mit.csail.sdg.alloy4.DirectedGraph in project org.alloytools.alloy by AlloyTools.

the class ExprUnary method resolveClosure.

// ============================================================================================================//
/**
 * Helper method that computes the relevant type for a closure expression.
 * <p>
 * Return Value == { c1->c2 | c1->c2 in childType, AND exists p1->p2 in
 * parentType where p1..c1..c2..p2 is a path in the closure graph }
 * <p>
 * We need to do this because of situations like this follow: Suppose e's type
 * is "A->B + B->C". Therefore, ^e = A->B + B->C + A->C which makes sense. But
 * as we compute the relevance type back down, we may have lost some entries,
 * and possibly end up with only A->B + A->C so we need to rediscover the
 * relevant edges.
 */
private static Type resolveClosure(Type parent, Type child) {
    LinkedHashSet<PrimSig> nodes = new LinkedHashSet<PrimSig>();
    DirectedGraph<PrimSig> graph = new DirectedGraph<PrimSig>();
    // For each (v1->v2) in childType, add (v1->v2) into the graph.
    for (ProductType c : child) if (c.arity() == 2) {
        PrimSig a = c.get(0), b = c.get(1);
        nodes.add(a);
        nodes.add(b);
        graph.addEdge(a, b);
    }
    // edges v1->v2 and v2->v1.
    for (PrimSig a : nodes) for (PrimSig b : nodes) if (a != b && a.intersects(b))
        graph.addEdge(a, b);
    // them.
    for (ProductType p : parent) if (p.arity() == 2) {
        PrimSig a = p.get(0), b = p.get(1);
        // Add edges between a and all its subtypes and supertypes
        if (!nodes.contains(a)) {
            for (PrimSig x : nodes) if (a.intersects(x)) {
                graph.addEdge(a, x);
                graph.addEdge(x, a);
            }
            nodes.add(a);
        }
        // Add edges between b and all its subtypes and supertypes
        if (!nodes.contains(b)) {
            for (PrimSig x : nodes) if (b.intersects(x)) {
                graph.addEdge(b, x);
                graph.addEdge(x, b);
            }
            nodes.add(b);
        }
    }
    // For each c1->c2 in childType, add c1->c2 into the finalType if there
    // exists p1->p2 in parentType
    // such that p1->..->c1->c2->..->p2 is a path in the graph.
    Type answer = Type.EMPTY;
    for (ProductType c : child) if (c.arity() == 2) {
        PrimSig c1 = c.get(0), c2 = c.get(1);
        for (ProductType p : parent) if (p.arity() == 2) {
            PrimSig p1 = p.get(0), p2 = p.get(1);
            if (graph.hasPath(p1, c1) && graph.hasPath(c2, p2)) {
                answer = answer.merge(c);
                break;
            }
        }
    }
    return answer;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) ProductType(edu.mit.csail.sdg.ast.Type.ProductType) DirectedGraph(edu.mit.csail.sdg.alloy4.DirectedGraph) ProductType(edu.mit.csail.sdg.ast.Type.ProductType) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Aggregations

DirectedGraph (edu.mit.csail.sdg.alloy4.DirectedGraph)1 ErrorType (edu.mit.csail.sdg.alloy4.ErrorType)1 PrimSig (edu.mit.csail.sdg.ast.Sig.PrimSig)1 ProductType (edu.mit.csail.sdg.ast.Type.ProductType)1 LinkedHashSet (java.util.LinkedHashSet)1