package org.archstudio.prolog.op.iso; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.archstudio.prolog.engine.PrologUtils; import org.archstudio.prolog.engine.ProofContext; import org.archstudio.prolog.engine.Signature; import org.archstudio.prolog.engine.UnificationContext; import org.archstudio.prolog.engine.UnificationEngine; import org.archstudio.prolog.term.ComplexTerm; import org.archstudio.prolog.term.Term; import org.archstudio.prolog.term.VariableTerm; import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; public class Neck extends ComplexTerm { final Set<VariableTerm> allVariables; public Neck(String functor, List<? extends Term> terms) { super(functor, 2, terms); allVariables = PrologUtils.extractVariables(Sets.<VariableTerm> newHashSet(), this); } @Override public Signature getSignature() { return ((ComplexTerm) getTerm(0)).getSignature(); } @Override public Iterable<Map<VariableTerm, Term>> execute(final ProofContext proofContext, final UnificationEngine unificationEngine, final Term source, final Map<VariableTerm, Term> variables) { final Map<VariableTerm, Term> temporaryVariables = Maps.newHashMapWithExpectedSize(allVariables.size()); for (VariableTerm v : allVariables) { temporaryVariables.put(v, PrologUtils.getTemporaryVariableTerm()); } Neck n = (Neck) resolve(proofContext, temporaryVariables); final UnificationContext context = new UnificationContext(proofContext, source, n.getTerm(0), variables); if (unificationEngine.unifies(proofContext, context)) { return Iterables.transform(PrologUtils.resolveExecutable(proofContext, n.getTerm(1), context.variables) .execute(proofContext, unificationEngine, source, context.variables), new Function<Map<VariableTerm, Term>, Map<VariableTerm, Term>>() { @Override public Map<VariableTerm, Term> apply(Map<VariableTerm, Term> input) { for (Entry<VariableTerm, Term> e : input.entrySet()) { e.setValue(e.getValue().resolve(proofContext, input)); } for (Term temporaryVariable : temporaryVariables.values()) { input.remove(temporaryVariable); } return input; } }); } return Collections.emptyList(); } }