package com.klq.typechecker;
import com.klq.ast.impl.expr.IdentifierNode;
import java.util.*;
/**
* Created by juriaan on 2-3-15.
*/
public class CyclicDetector {
private Map<IdentifierNode, Set<IdentifierNode>> dependencies;
private Map<IdentifierNode, Set<IdentifierNode>> fullDependencies;
public CyclicDetector() {
this.dependencies = new HashMap<>();
this.fullDependencies = new HashMap<>();
}
public void addKey(IdentifierNode key){
if(!dependencies.containsKey(key)) {
dependencies.put(key, new HashSet<>());
}
}
public void addDependency(IdentifierNode key, IdentifierNode dependency){
if(dependencies.containsKey(key)){
dependencies.get(key).add(dependency);
}
}
public boolean hasCycles(){
for(Map.Entry<IdentifierNode, Set<IdentifierNode>> entry : fullDependencies.entrySet()){
if( entry.getValue().contains(entry.getKey())){
return true;
}
}
return false;
}
public void calculateFullDependencies(){
fullDependencies = new HashMap<>();
for(Map.Entry<IdentifierNode, Set<IdentifierNode>> entry : dependencies.entrySet()){
fullDependencies.put(entry.getKey(), findDependencies(entry.getValue(), new ArrayList<>()));
}
}
public List<IdentifierNode> getCyclicIds(){
List<IdentifierNode> list = new ArrayList<>();
for(Map.Entry<IdentifierNode, Set<IdentifierNode>> entry : fullDependencies.entrySet()){
if( entry.getValue().contains(entry.getKey())){
list.add(entry.getKey());
}
}
return list;
}
private Set<IdentifierNode> findDependencies(Set<IdentifierNode> set, List<IdentifierNode> visited){
Set<IdentifierNode> newSet = new HashSet<>();
newSet.addAll(set);
for(IdentifierNode item : set){
if(!visited.contains(item)) {
visited.add(item);
newSet.addAll(findDependencies(dependencies.get(item), visited));
}
}
return newSet;
}
}