public bool UnifiesNoUndo(ITerm term, ITerm term2) { if (term == null && term2 == null) { return(true); } if (term == null && term2 != null) { return(false); } if (term != null && term2 == null) { return(false); } Pred np1 = null; Pred np2 = null; if (np1.GetType() == typeof(Pred) && np2.GetType() == typeof(Pred)) { np1 = (Pred)term; np2 = (Pred)term2; // tests when np1 or np2 are variables with annotations if (np1.IsVar() && np1.HasAnnot() || np2.IsVar() && np2.HasAnnot()) { if (!np1.HasSubsetAnnot(np2, this)) { return(false); } } } if (term.IsCyclicTerm() && term2.IsCyclicTerm()) // Both are cycled terms { // Unification of cyclic terms: Remove variables to avoid loops and test the structure, then reintroduce vars VarTerm v1 = term.GetCyclicVar(); VarTerm v2 = term2.GetCyclicVar(); Remove(v1); Remove(v2); try { return(UnifiesNoUndo(new LiteralImpl((Literal)term), new LiteralImpl((Literal)term2))); } finally { function.Add(v1, term); function.Add(v2, term2); } } else { if (term.IsCyclicTerm() && Get(term.GetCyclicVar()) == null) // Reintroduce cycles in the unifier { function.Add(term.GetCyclicVar(), term); } if (term2.IsCyclicTerm() && Get(term.GetCyclicVar()) == null) { function.Add(term2.GetCyclicVar(), term2); } } // Unify as Term bool ok = UnifyTerms(term, term2); // If term is a unified variable, clear its annotations if (ok && term != null) // Both are predicates { if (term.IsVar() && ((Pred)term).HasAnnot()) { term = Deref((VarTerm)term); // ??? ITerm termvl; function.TryGetValue((VarTerm)term, out termvl); if (termvl != null && termvl.IsPred()) { Pred pvl = (Pred)termvl.Clone(); pvl.ClearAnnots(); Bind((VarTerm)term, pvl); } } if (term2.IsVar() && ((Pred)term2).HasAnnot()) { term2 = Deref((VarTerm)term2); ITerm term2vl; function.TryGetValue((VarTerm)term2, out term2vl); if (term2vl != null && term2vl.IsPred()) { Pred pvl = (Pred)term2vl.Clone(); pvl.ClearAnnots(); Bind((VarTerm)term2, pvl); } } } return(ok); }