package org.archstudio.prolog.op.iso;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.archstudio.prolog.engine.PrologUtils;
import org.archstudio.prolog.engine.ProofContext;
import org.archstudio.prolog.engine.UnificationEngine;
import org.archstudio.prolog.op.Executable;
import org.archstudio.prolog.term.ComplexTerm;
import org.archstudio.prolog.term.Term;
import org.archstudio.prolog.term.VariableTerm;
import com.google.common.collect.AbstractIterator;
public class Conjunction extends ComplexTerm implements Executable {
public Conjunction(String name, List<? extends Term> terms) {
super(name, 2, terms);
}
@Override
public Iterable<Map<VariableTerm, Term>> execute(final ProofContext t0ProofContext,
final UnificationEngine unificationEngine, Term source, final Map<VariableTerm, Term> variables) {
final Executable t0 = PrologUtils.resolveExecutable(t0ProofContext, getTerm(0), variables);
return new Iterable<Map<VariableTerm, Term>>() {
@Override
public Iterator<Map<VariableTerm, Term>> iterator() {
return new AbstractIterator<Map<VariableTerm, Term>>() {
Iterator<Map<VariableTerm, Term>> t0Variables = t0.execute(t0ProofContext, unificationEngine, t0,
variables).iterator();
Iterator<Map<VariableTerm, Term>> t1Variables = PrologUtils.emptyVariablesList().iterator();
// if term0 is the cut operator, then create a new cut context for term1
ProofContext t1ProofContext = t0 instanceof Cut ? new ProofContext(t0ProofContext) : t0ProofContext;
@Override
protected Map<VariableTerm, Term> computeNext() {
while (true) {
if (t0ProofContext.isCancelled()) {
return endOfData();
}
if (t1Variables.hasNext()) {
return t1Variables.next();
}
if (t0Variables.hasNext()) {
Map<VariableTerm, Term> variables = t0Variables.next();
Executable t1 = PrologUtils.resolveExecutable(t1ProofContext, getTerm(1), variables);
t1Variables = t1.execute(t1ProofContext, unificationEngine, t1, variables).iterator();
continue;
}
return endOfData();
}
}
};
}
};
}
}