package typeChecker;
import java.util.LinkedList;
import java.util.List;
import nodeAST.ASTNode;
import nodeAST.Expression;
import nodeAST.Ident;
import nodeAST.syntactic.Question;
import nodeAST.syntactic.QuestionBody;
import types.Type;
import visitor.ASTVisitor;
public class CyclicDependencies extends ASTVisitor {
protected List<Question> questions;
protected List<Question> dependencies;
public CyclicDependencies() {
this.questions=new LinkedList<>();
this.dependencies=null;
}
public void check(ASTNode root) throws Exception {
List<Question> list = findCycles(root);
if(list.size()!=0) {
String message= "ERROR: The following questions form a cycle of dependencies: \n";
for(Question q: list)
message+=q.toString()+"\n";
throw new Exception(message);
}
}
private List<Question> findCycles(ASTNode root) {
root.accept(this);
for (Question q: questions) {
this.dependencies=new LinkedList<>();
this.dependencies.add(q);
for(int i=0; i<= this.questions.size()+2; i++)
root.accept(this);
if(dependencies.size() > this.questions.size())
return getFirstCycle(this.dependencies);
}
return new LinkedList<>();
}
private List<Question> getFirstCycle(List<Question> dependencies) {
List<Question> returnList=new LinkedList<>();
for(int i=0; i< dependencies.size(); i++) {
Question el = dependencies.get(i);
if(returnList.contains(el)) {
returnList.add(el);
break;
}
returnList.add(el);
}
return returnList;
}
@Override
public void visit(Question q, Ident ident,
QuestionBody questionBody, Type type, Expression expr) {
if(this.dependencies == null)
this.questions.add(q);
else {
Ident lastIdent=this.dependencies.get(dependencies.size()-1).getIdent();
if(q.hasExpression() &&
q.getExpression().containsTreeNode(
lastIdent)
)
this.dependencies.add(q);
}
}
}