package org.smoothbuild.parse;
import java.util.ArrayDeque;
import java.util.Deque;
import org.smoothbuild.cli.Console;
import org.smoothbuild.lang.function.base.Name;
import org.smoothbuild.lang.message.CodeLocation;
public class DependencyStack {
private final Deque<DependencyStackElem> stack = new ArrayDeque<>();
public boolean isEmpty() {
return stack.isEmpty();
}
public void push(DependencyStackElem element) {
stack.addLast(element);
}
public DependencyStackElem pop() {
return stack.removeLast();
}
public DependencyStackElem peek() {
return stack.getLast();
}
public void reportAndThrowCycleException(Console console) {
Name lastMissing = peek().missing().functionName();
int first = -1;
DependencyStackElem[] array = stack.toArray(new DependencyStackElem[stack.size()]);
for (int i = array.length - 1; 0 <= i; i--) {
if (array[i].name().equals(lastMissing)) {
first = i;
break;
}
}
if (first == -1) {
throw new IllegalStateException("Couldn't find expected cycle in call graph.");
}
StringBuilder builder = new StringBuilder();
for (int i = first; i < array.length; i++) {
DependencyStackElem current = array[i];
Dependency missing = current.missing();
builder.append(current.name().value() + missing.location() + " -> " + missing.functionName()
.value() + "\n");
}
CodeLocation location = array[first].missing().location();
console.error(location, "Function call graph contains cycle:\n" + builder.toString());
throw new ParsingException();
}
}