private void ExecuteRewriteForRule(InterpreterEvaluationTerm termToRewrite, TrsReductionRule rule, UnificationResult composedUnifier) { bool rewritingTookPlaceLocal = false; if (composedUnifier.Succeed) { if (rule.Tail.GetType() == typeof(TrsNativeKeyword)) { // Replacing term value with a native function generated value var nativeTermInHead = ((TrsTermBase)termToRewrite.CurrentSubTerm.CreateCopy()).ApplySubstitutions(composedUnifier.Unifier); foreach (var native in nativeFunctions) { var processedTerm = native.Evaluate(nativeTermInHead); if (processedTerm == null) { throw new Exception(string.Format("Native function in type {0} returned null", native.GetType().FullName)); } // If the rewrite result is the same, no rewriting took place ... if (!nativeTermInHead.Equals(processedTerm)) { var newTerm = termToRewrite.RootTerm.CreateCopyAndReplaceSubTerm(termToRewrite.CurrentSubTerm, processedTerm); rewritingTookPlaceLocal = true; var newTermWrapper = new InterpreterTerm(newTerm); newTermWrapper.IsNewTerm = true; executionCache.Add(newTermWrapper); } } } else { // Normal rewriting without native eval functions var replacementTerm = ((TrsTermBase)rule.Tail.CreateCopy()).ApplySubstitutions(composedUnifier.Unifier); if (!termToRewrite.CurrentSubTerm.Equals(replacementTerm)) { var newTerm = termToRewrite.RootTerm.CreateCopyAndReplaceSubTerm(termToRewrite.CurrentSubTerm, replacementTerm); rewritingTookPlaceLocal = true; var newTermWrapper = new InterpreterTerm(newTerm); newTermWrapper.IsNewTerm = true; executionCache.Add(newTermWrapper); } } } if (rewritingTookPlaceLocal) { rewritingTookPlace = true; // stops rewriting on next rewrite step termToRewrite.CacheSourceTerm.MustDeletFromCache = true; } }
private void ApplyReductionRuleToCache(TrsReductionRule rule) { // This data structure stores the Cartesian product used for term products // The length of each sub-List is the size of an alphabet for calculating a "Godel string" of terms. // This avoids the need for seperate sub-enumerators. var rewriteCandidates = new List <List <InterpreterEvaluationTerm> >(); // Populate the rewriteCandidates TrsTermProduct ruleHead = (TrsTermProduct)rule.Head; int productLength = ruleHead.TermList.Count; for (int termProductIndex = 0; termProductIndex < productLength; termProductIndex++) { rewriteCandidates.Add(new List <InterpreterEvaluationTerm>()); foreach (var termInCache in executionCache) { // Do not rewrite new terms, we are doing one rewrite step at a time if (termInCache.IsNewTerm) { continue; } // Test all sub-terms var expantionStack = new Stack <TrsTermBase>(); expantionStack.Push(termInCache.RootTerm); while (expantionStack.Count > 0) { var current = expantionStack.Pop(); // Ignore the "variable only" case to avoid matching all rewrite rules to a sub-term. if (current is TrsVariable) { continue; } // Type rules applied here ... cater for multiple unification results by duplicating candidates foreach (var unifier in mguCalculation.GetUnifier(ruleHead.TermList[termProductIndex], current)) { if (IsUnifierValid(unifier, ruleHead.TermList[termProductIndex])) { rewriteCandidates[termProductIndex].Add(new InterpreterEvaluationTerm(termInCache.RootTerm, current, termInCache, unifier)); } } // Apply rewrite rule to subterms if (current is TrsTerm) { foreach (var subTerm in ((TrsTerm)current).Arguments) { expantionStack.Push(subTerm); } } else if (current is TrsAcTerm) { foreach (var subTerm in ((TrsAcTerm)current).OnfArguments) { expantionStack.Push(subTerm.Term); } } } } } // Execute rewite step ... iterate over cartesian term product // This iterationCount variable will prevent rewriting in the case where any of the lists are empty int iterationCount = rewriteCandidates.First().Count; foreach (var termList in rewriteCandidates.Skip(1)) { iterationCount *= termList.Count; } var matchTupple = new List <InterpreterEvaluationTerm>(rewriteCandidates.Count); for (int tuppleNumber = 0; tuppleNumber < iterationCount; tuppleNumber++) { var currDiv = tuppleNumber; UnificationResult currentUnifier = null; UnificationResult testUnifier = null; matchTupple.Clear(); // In order to do a substitution, all variables must bind to the same values across the tupple members for (int termColumn = 0; termColumn < rewriteCandidates.Count; termColumn++) { var currMod = currDiv % rewriteCandidates[termColumn].Count; currDiv = currDiv / rewriteCandidates[termColumn].Count; var targetTerm = rewriteCandidates[termColumn][currMod]; currentUnifier = targetTerm.Unifier; if (testUnifier == null) { testUnifier = currentUnifier; } matchTupple.Add(targetTerm); } var termProductUnifier = ComposeUnifiers(matchTupple.Select(term => term.Unifier)); if (termProductUnifier.Succeed) { foreach (var term in matchTupple) { ExecuteRewriteForRule(term, rule, termProductUnifier); } } } }