private static void Bind( Set <StdTerm> allVars, EquivalenceRelation <StdTerm> eqs, Stack <Tuple <StdTerm, StdTerm> > pending, StdTerm bindee, StdTerm binding) { if (eqs.Equals(bindee, binding)) { return; } var index = bindee.term.Owner; Contract.Assert(bindee.term.Symbol == index.SelectorSymbol || bindee.term.Symbol.IsVariable); Contract.Assert(binding.term.Symbol == index.SelectorSymbol || binding.term.Symbol.IsVariable || binding.term.Symbol.IsDataConstructor || binding.term.Symbol.IsNonVarConstant); RegisterSelectors(allVars, eqs, bindee); if (binding.term.Symbol.IsDataConstructor || binding.term.Symbol.IsNonVarConstant) { var crntBinding = eqs.SetTracker(bindee, Track_FreeApply, binding); if (StdTerm.Compare(crntBinding, binding) != 0) { pending.Push(new Tuple <StdTerm, StdTerm>(crntBinding, binding)); } binding.term.Visit( x => x.Groundness == Groundness.Variable && x.Symbol.IsDataConstructor ? x.Args : null, x => { if (x.Symbol.IsVariable || x.Symbol == index.SelectorSymbol) { RegisterSelectors(allVars, eqs, x.Standardize(binding.label)); eqs.AddToTrackSet(bindee, Track_FreeOccurs, x.Standardize(binding.label)); } }); } else { RegisterSelectors(allVars, eqs, binding); } eqs.Equate(bindee, binding); }
public static bool IsUnifiable(Term tA, Term tB, bool standardize = true) { Contract.Requires(tA != null && tB != null); Contract.Requires(tA.Owner == tB.Owner); var eqs = new EquivalenceRelation <StdTerm>(StdTerm.Compare, 1, 1); var success = new SuccessToken(); var relabelSymbol = tA.Owner.SymbolTable.GetOpSymbol(ReservedOpKind.Relabel); var pending = new Stack <Tuple <StdTerm, StdTerm> >(); pending.Push(new Tuple <StdTerm, StdTerm>(tA.Standardize(0), tB.Standardize(standardize ? 1 : 0))); int lblA, lblB; Term trmA, trmB; Tuple <StdTerm, StdTerm> top; Set <StdTerm> allVars = new Set <StdTerm>(StdTerm.Compare); while (pending.Count > 0) { top = pending.Pop(); if (StdTerm.Compare(top.Item1, top.Item2) == 0) { continue; } top.GetComponents(out trmA, out lblA, out trmB, out lblB); trmA.Compute <Unit>( trmB, (xA, xB, s) => { if (xA.Symbol == relabelSymbol) { xA = EliminateRelabel(xA); } if (xB.Symbol == relabelSymbol) { xB = EliminateRelabel(xB); } if (xA.Groundness == Groundness.Ground && xB.Groundness == Groundness.Ground) { //// If x1 and x2 are ground, then just check equality. if (xA != xB) { success.Failed(); } return(null); } else if ((xA.Symbol.IsDataConstructor || xA.Symbol.IsNonVarConstant) && (xB.Symbol.IsDataConstructor || xB.Symbol.IsNonVarConstant)) { //// If x1 and x2 are both data constructors, //// then check symbol equality and unroll. if (xA.Symbol != xB.Symbol) { success.Failed(); return(null); } return(new Tuple <IEnumerable <Term>, IEnumerable <Term> >(xA.Args, xB.Args)); } else if (xA.Symbol.IsVariable || xA.Symbol == xA.Owner.SelectorSymbol) { Bind(allVars, eqs, pending, xA.Standardize(lblA), xB.Standardize(lblB)); return(null); } else { Bind(allVars, eqs, pending, xB.Standardize(lblB), xA.Standardize(lblA)); return(null); } }, (xA, xB, ch, s) => { return(default(Unit)); }, success); } if (!success.Result) { return(false); } return(OccursCheck(allVars, eqs)); }
private static Term MkMGU(StdTerm t, EquivalenceRelation <StdTerm> eqs, Func <int, Term> varCreator) { Term normVar; StdTerm stdRep, stdX; int i, label; bool wasAdded; var varMap = new Map <StdTerm, Term>(StdTerm.Compare); var labelStack = new Stack <int>(); labelStack.Push(t.label); var result = t.term.Compute <Term>( (x, s) => { if (x.Groundness == Groundness.Ground) { labelStack.Push(labelStack.Peek()); return(null); } else if (!x.Symbol.IsVariable) { labelStack.Push(labelStack.Peek()); return(x.Args); } stdX = x.Standardize(labelStack.Peek()); if (eqs.GetTracker(stdX, Track_FreeApply, out stdRep)) { labelStack.Push(stdRep.label); return(EnumerableMethods.GetEnumerable <Term>(stdRep.term)); } else if (StdTerm.Compare(stdRep = eqs.GetRepresentative(stdX), stdX) == 0) { labelStack.Push(labelStack.Peek()); return(null); } else { labelStack.Push(stdRep.label); return(EnumerableMethods.GetEnumerable <Term>(stdRep.term)); } }, (x, c, s) => { label = labelStack.Pop(); if (x.Groundness == Groundness.Ground) { return(x); } else if (!x.Symbol.IsVariable) { i = 0; var args = new Term[x.Symbol.Arity]; foreach (var tp in c) { args[i++] = tp; } return(x.Owner.MkApply(x.Symbol, args, out wasAdded)); } if (c.IsEmpty <Term>()) { if (!varMap.TryFindValue(x.Standardize(label), out normVar)) { normVar = varCreator(varMap.Count); varMap.Add(x.Standardize(label), normVar); } return(normVar); } else { return(c.First <Term>()); } }); Contract.Assert(labelStack.Count == 1); return(result); }