/// <summary> /// Gets the locators of this locators subterms /// </summary> public override Locator this[int index] { get { Contract.Assert(index >= 0 && index < Arity); bool gotLock = false; try { argsLock.Enter(ref gotLock); if (args != null) { return(args[index]); } args = new NodeTermLocator[locatorTerm.Symbol.Arity]; FuncTerm ftnode; if (locatorNode.NodeKind == NodeKind.FuncTerm && (ftnode = (FuncTerm)locatorNode).Args.Count == locatorTerm.Symbol.Arity) { int i = 0; foreach (var a in ftnode.Args) { args[i] = new NodeTermLocator(a, locatorTerm.Args[i]); ++i; } } else { for (int i = 0; i < locatorTerm.Args.Length; ++i) { args[i] = new NodeTermLocator(locatorNode, locatorTerm.Args[i]); } } return(args[index]); } finally { if (gotLock) { argsLock.Exit(); } } } }
/// <summary> /// Computes a set of locators /// </summary> /// <returns></returns> public LinkedList <Locator> ComputeLocators() { if (CoreRule == null) { //// Then this is a fact. ModelFactLocator loc; var locs = new LinkedList <Locator>(); //// Not implemented for renamed fact sets. Return some locator associated with some fact set. if (factSets.Count > 1 || !factSets.ContainsKey(string.Empty) || !factSets[string.Empty].TryGetLocator(Conclusion, out loc)) { using (var it = factSets.GetEnumerator()) { it.MoveNext(); locs.AddLast(new NodeTermLocator( it.Current.Value.Model.Node, Conclusion)); } } else { locs.AddLast(loc); } return(locs); } else if (premises.Count == 0) { var locs = new LinkedList <Locator>(); locs.AddLast(new NodeTermLocator( CoreRule.Node, Conclusion)); return(locs); } else { Contract.Assert(CoreRule.Kind == CoreRule.RuleKind.Regular); FactSet sourceFacts; if (factSets.TryFindValue(string.Empty, out sourceFacts) && sourceFacts.Rules.IsSubRuleCopy(CoreRule)) { Contract.Assert(premises.Count == 1); var inputProof = premises.First().Value.Item2; return(MkSubRuleLocators( CoreRule.Node, inputProof.Conclusion, Conclusion, inputProof.ComputeLocators())); } //// Terms in the body for which locations are known. var bodyTerm2Locs = new Map <Term, LinkedList <Locator> >(Term.Compare); //// The bindings of body variables implied by the binding variable and its pattern. var bodyVar2Bindings = new Map <Term, Term>(Term.Compare); //// Records to the set of variable bindings in this pass. var newVarBindings = new Stack <Term>(); foreach (var kv in premises) { MkBodyLocators( kv.Value.Item2.ComputeLocators(), kv.Value.Item2.Conclusion, kv.Key, kv.Value.Item1, bodyTerm2Locs, bodyVar2Bindings, newVarBindings); } if (CoreRule.AdditionalVarDefs != null) { Set <Term> eqs; while (newVarBindings.Count > 0) { var x = newVarBindings.Pop(); if (!CoreRule.AdditionalVarDefs.TryFindValue(x, out eqs) || eqs.Count == 0) { continue; } var xlocs = bodyTerm2Locs[x]; var xbinding = bodyVar2Bindings[x]; foreach (var eq in eqs) { MkBodyLocators( xlocs, xbinding, x, eq, bodyTerm2Locs, bodyVar2Bindings, newVarBindings); } } } //// The bindings of variables or variable selectors implied by the conclusion and the head. //// A variable in the head may have multiple bindings due to renamings. var head2Bindings = new Map <Term, Set <Term> >(Term.Compare); MkHeadBindings(Conclusion, CoreRule.Head, head2Bindings, bodyTerm2Locs, bodyVar2Bindings); return(MkRuleLocators( NodeTermLocator.ChooseRepresentativeNode(CoreRule.Node, Conclusion), CoreRule.Head, head2Bindings, bodyTerm2Locs)); } }