public IEnumerable <Pair <T, SubstitutionSet> > Unify(Stack <Name> stack, SubstitutionSet binding) { if (stack.Count == 0) //End stack { if (m_hasValue) { yield return(Tuples.Create(m_value, binding)); } yield break; } TreeNode nodeToEvaluate; Name term = stack.Pop(); if (!term.IsVariable) { int numOfTerms = term.NumberOfTerms; if (numOfTerms == 1) { var selectedNodes = Enumerable.Empty <TreeNode>(); Name key = term; if (key.IsUniversal) { if (m_universal != null) { selectedNodes = selectedNodes.Append(m_universal); } selectedNodes = selectedNodes.Union(GetNextLevel().SelectMany(p => p.Item2)); } else { if (m_nextSymbol != null && m_nextSymbol.TryGetValue(key, out nodeToEvaluate)) { selectedNodes = selectedNodes.Append(nodeToEvaluate); } if (m_universal != null) { selectedNodes = selectedNodes.Append(m_universal); } } foreach (var pair in selectedNodes.SelectMany(n => n.Unify(stack, binding))) { yield return(pair); } } else { if (m_nextComposed != null && m_nextComposed.TryGetValue(numOfTerms, out nodeToEvaluate)) { using (var it = term.GetTerms().Reverse().GetEnumerator()) { while (it.MoveNext()) { stack.Push(it.Current); } } foreach (var pair in nodeToEvaluate.Unify(stack, binding)) { yield return(pair); } for (int i = 0; i < term.NumberOfTerms; i++) { stack.Pop(); } } if (m_universal != null) { foreach (var pair in m_universal.Unify(stack, binding)) { yield return(pair); } } } if (m_nextVariable != null) { //Find bindings with stored variables foreach (var pair in m_nextVariable) { var sub = new Substitution(pair.Key, new ComplexValue(term)); if (binding.Conflicts(sub)) { continue; } var set = new SubstitutionSet(binding); set.AddSubstitution(sub); foreach (var r in pair.Value.Unify(stack, set)) { yield return(r); } } } } else { //Find bindings var nextLevel = GetNextLevel(); foreach (var pair in nextLevel) { SubstitutionSet set = binding; if (!pair.Item1.IsVariable || pair.Item1 != term) { //Very odd trick to make certainty work var sub = new Substitution(term, new ComplexValue(pair.Item1, 1)); if (binding.Conflicts(sub)) { continue; } set = new SubstitutionSet(set); set.AddSubstitution(sub); } foreach (var node in pair.Item2) { foreach (var r in node.Unify(stack, set)) { yield return(r); } } } } stack.Push(term); }