private AltLoopStatus TryOneAlternative(int ip, VarStack varStack, ListPatternElem e, int k, int marker, ListTerm RangeList, int i, BaseTerm t, ref bool negSearchSucceeded, BaseTerm searchTerm) { bool unified = searchTerm.Unify(t, varStack); if (e.IsNegSearch) // none of the terms in the inner loop may match. ~(a | b | c) = ~a & ~b & ~c { if (unified) // ... no point in investigating the other alternatives if one does { negSearchSucceeded = false; return(AltLoopStatus.Break); // don't try the other alternatives } return(AltLoopStatus.TryNextDown); // non of the downranges matches may lead to a success } else { if (unified && // we found a match. Unify, and TryBindingAltListVarToMatch(e.AltListBindVar, t, varStack) && // bind the AltListBindVar to the match TryBindingRangeRelatedVars(e, i, RangeList, varStack)) // bind the range to the range variables { if (ip == pattern.Length - 1) // this was the last pattern element { if (k == target.Count - 1) // both pattern and target exhausted { return(AltLoopStatus.MatchFound); } } else if (UnifyTailEx(ip + 1, k + 1, varStack)) // now deal with the rest { return(AltLoopStatus.MatchFound); } } // if we arrive here, it was not possible to ... // (1) ... unify the range's SearchTerm with the target element, or // (2) ... unify the range variable with the range list, or // (3) ... successfully process the rest of the pattern and target // Now unbind and try matching with the next target element BaseTerm.UnbindToMarker(varStack, marker); return(AltLoopStatus.TryNextDown); // try the next downrange match } }
// each call processes one element of pattern[] bool UnifyTailEx(int ip, int it, VarStack varStack) { ListPatternElem e = (ListPatternElem)pattern[ip]; Variable rangeSpecVar = (Variable)e.RangeBindVar; NodeIterator subtreeIterator; int k; int marker; ListTerm RangeList = null; BaseTerm tail = null; int minLen; // minimum required range length (number of range elements) int maxLen; // maximum possible ... if (!DoLowerAndUpperboundChecks(ip, it, out minLen, out maxLen)) { return(false); } // scan the minimal number of range elements. Add them to the range list, // i.e. the last variable (if present) preceding the '{ , }' for (int i = 0; i < minLen; i++) { if ((k = it + i) >= target.Count) { return(false); } AppendToRangeList(ref RangeList, rangeSpecVar, target[k], ref tail); } marker = varStack.Count; // register the point to which we must possibly undo unifications if (e.HasSearchTerm) { // scan the elements up to the maximum range length, and the element immediately thereafter for (int i = minLen; i <= maxLen; i++) { BaseTerm t = null; k = it + i; if (k == target.Count) { return(false); } bool negSearchSucceeded = true; // iff none of the alternative term matches the target term for (int j = 4; j < e.Args.Length; j++) // scan all AltSearchTerm alternatives (separated by '|') { BaseTerm searchTerm = e.AltSearchTerms[j]; DownRepFactor downRepFactor = null; // e.downRepFactor [j]; t = target[k]; AltLoopStatus status = AltLoopStatus.TryNextAlt; if (downRepFactor == null) { status = TryOneAlternative(ip, varStack, e, k, marker, RangeList, i, t, ref negSearchSucceeded, searchTerm); if (status == AltLoopStatus.MatchFound) { return(true); } } else // traverse the downRepFactor tree, which in principle may yield more than one match { subtreeIterator = new NodeIterator(t, searchTerm, downRepFactor.minLenTerm, downRepFactor.maxLenTerm, false, downRepFactor.bindVar, varStack); foreach (BaseTerm match in subtreeIterator) // try -- if necessary -- each tree match with the current search term { status = TryOneAlternative(ip, varStack, e, k, marker, RangeList, i, match, ref negSearchSucceeded, searchTerm); if (status == AltLoopStatus.MatchFound) { return(true); } if (status == AltLoopStatus.Break) { break; } } } if (status == AltLoopStatus.Break) { break; } } // at this point sufficient alternatives have been tried if (e.IsNegSearch && negSearchSucceeded) // none of the terms matched => ok if binding succeeds { if (!TryBindingAltListVarToMatch(e.AltListBindVar, t, varStack) || // bind the AltListBindVar to the match !TryBindingRangeRelatedVars(e, i, RangeList, varStack)) // bind the range to the range variables { return(false); // binding failed } if (ip == pattern.Length - 1) // this was the last pattern element { if (k == target.Count - 1) // both pattern and target exhausted { return(true); } } else if (UnifyTailEx(ip + 1, k + 1, varStack)) // now deal with the rest { return(true); } } else if (i < maxLen) // append the rejected term to the range list and go try the next term { AppendToRangeList(ref RangeList, rangeSpecVar, t, ref tail); } } } else // a range without a subsequent search term (so followed by another range or end of pattern) { for (int i = minLen; i <= maxLen; i++) { k = it + i; if (k == target.Count) // ok, target[k] does not exist, end of target hit { return(TryBindingRangeRelatedVars(e, i, RangeList, varStack)); // i is actual range length } // k is ok if (i < maxLen) { AppendToRangeList(ref RangeList, rangeSpecVar, target[k], ref tail); } // now deal with the rest if (TryBindingRangeRelatedVars(e, i, RangeList, varStack) && UnifyTailEx(ip + 1, k, varStack)) { return(true); } } } // If we arrive here, no matching term was found in or immediately after the permitted range. // Therefore, undo any unifications made locally in this method and return with failure. if (marker != 0) { BaseTerm.UnbindToMarker(varStack, marker); } return(false); }