#include "Shell/Options.hpp"
#include "Ordering.hpp"
#include "SortHelper.hpp"
#include "TermIterators.hpp"
#include "Lib/Metaiterators.hpp"
#include "Matcher.hpp"
#include "EqHelper.hpp"
namespace Kernel {
using namespace Shell;
template<class TermListIter>
auto withEqualitySort(Literal* eq, TermListIter iter)
{
ASS(iter.hasNext());
auto sort = SortHelper::getEqualityArgumentSort(eq);
return pvi(iterTraits(std::move(iter))
.map([sort](TermList t) { return TypedTermList(t, sort); }));
}
TermList EqHelper::getOtherEqualitySide(Literal* eq, TermList lhs)
{
ASS(eq->isEquality());
if (*eq->nthArgument(0) == lhs) {
return *eq->nthArgument(1);
}
ASS(*eq->nthArgument(1) == lhs);
return *eq->nthArgument(0);
}
bool EqHelper::hasGreaterEqualitySide(Literal* eq, const Ordering& ord, TermList& lhs, TermList& rhs)
{
ASS(eq->isEquality());
switch(ord.getEqualityArgumentOrder(eq)) {
case Ordering::INCOMPARABLE:
return false;
case Ordering::GREATER:
lhs = *eq->nthArgument(0);
rhs = *eq->nthArgument(1);
return true;
case Ordering::LESS:
lhs = *eq->nthArgument(1);
rhs = *eq->nthArgument(0);
return true;
case Ordering::EQUAL:
ASSERTION_VIOLATION;
}
ASSERTION_VIOLATION;
}
Literal* EqHelper::replace(Literal* lit, TermList what, TermList by)
{
return static_cast<Literal*>(replace(static_cast<Term*>(lit), what, by));
}
Term* EqHelper::replace(Term* trm0, TermList tSrc, TermList tDest)
{
ASS(trm0->shared());
ASS(!trm0->isSort());
ASS(tSrc.isVar() || !tSrc.term()->isSort());
ASS(tDest.isVar() || !tDest.term()->isSort());
static Stack<TermList*> toDo(8);
static Stack<Term*> terms(8);
static Stack<bool> modified(8);
static Stack<TermList> args(8);
ASS(toDo.isEmpty());
ASS(terms.isEmpty());
modified.reset();
args.reset();
modified.push(false);
toDo.push(trm0->args());
for (;;) {
TermList* tt=toDo.pop();
if (tt->isEmpty()) {
if (terms.isEmpty()) {
ASS(toDo.isEmpty());
break;
}
Term* orig=terms.pop();
if (!modified.pop()) {
args.truncate(args.length() - orig->arity());
args.push(TermList(orig));
continue;
}
TermList* argLst=&args.top() - (orig->arity()-1);
args.truncate(args.length() - orig->arity());
args.push(TermList(Term::create(orig,argLst)));
modified.setTop(true);
continue;
}
toDo.push(tt->next());
TermList tl=*tt;
if (tl == tSrc) {
args.push(tDest);
modified.setTop(true);
continue;
}
if (tl.isVar() || tl.term()->isSort()) {
args.push(tl);
continue;
}
ASS(tl.isTerm());
Term* t=tl.term();
terms.push(t);
modified.push(false);
toDo.push(t->args());
}
ASS(toDo.isEmpty());
ASS(terms.isEmpty());
ASS_EQ(modified.length(),1);
ASS_EQ(args.length(),trm0->arity());
if (!modified.pop()) {
return trm0;
}
TermList* argLst=&args.top() - (trm0->arity()-1);
if (trm0->isLiteral()) {
Literal* lit = static_cast<Literal*>(trm0);
ASS_EQ(args.size(), lit->arity());
return Literal::create(lit,argLst);
}
return Term::create(trm0,argLst);
}
VirtualIterator<Term*> EqHelper::getSubtermIterator(Literal* lit, const Ordering& ord)
{
return getRewritableSubtermIterator<NonVariableNonTypeIterator>(lit, ord);
}
TermIterator EqHelper::getBooleanSubtermIterator(Literal* lit, const Ordering& ord)
{
return getRewritableSubtermIterator<BooleanSubtermIt>(lit, ord);
}
template<class SubtermIterator>
VirtualIterator<ELEMENT_TYPE(SubtermIterator)> EqHelper::getRewritableSubtermIterator(Literal* lit, const Ordering& ord)
{
if (lit->isEquality()) {
TermList sel;
switch(ord.getEqualityArgumentOrder(lit)) {
case Ordering::INCOMPARABLE: {
SubtermIterator si(lit);
return getUniquePersistentIteratorFromPtr(&si);
}
case Ordering::EQUAL:
case Ordering::GREATER:
sel=*lit->nthArgument(0);
break;
case Ordering::LESS:
sel=*lit->nthArgument(1);
break;
#if VDEBUG
default:
ASSERTION_VIOLATION;
#endif
}
if (!sel.isTerm()) {
return VirtualIterator<ELEMENT_TYPE(SubtermIterator)>::getEmpty();
}
return getUniquePersistentIterator(vi(new SubtermIterator(sel.term(), true)));
}
SubtermIterator si(lit);
return getUniquePersistentIteratorFromPtr(&si);
}
VirtualIterator<TypedTermList> EqHelper::getLHSIterator(Literal* lit, const Ordering& ord)
{
if (lit->isEquality()) {
if (lit->isNegative()) {
return VirtualIterator<TypedTermList>::getEmpty();
}
TermList t0=*lit->nthArgument(0);
TermList t1=*lit->nthArgument(1);
switch(ord.getEqualityArgumentOrder(lit))
{
case Ordering::INCOMPARABLE:
return withEqualitySort(lit, iterItems(t0, t1) );
case Ordering::GREATER:
return withEqualitySort(lit, iterItems(t0) );
case Ordering::LESS:
return withEqualitySort(lit, getSingletonIterator(t1) );
case Ordering::EQUAL:
ASSERTION_VIOLATION;
}
return VirtualIterator<TypedTermList>::getEmpty();
} else {
return VirtualIterator<TypedTermList>::getEmpty();
}
}
struct EqHelper::IsNonVariable
{
bool operator()(TermList t)
{ return t.isTerm(); }
};
VirtualIterator<TypedTermList> EqHelper::getSuperpositionLHSIterator(Literal* lit, const Ordering& ord, const Options& opt)
{
if (opt.superpositionFromVariables()) {
return getLHSIterator(lit, ord);
}
else {
return pvi( getFilteredIterator(getLHSIterator(lit, ord), IsNonVariable()) );
}
}
std::pair<VirtualIterator<TypedTermList>,bool> EqHelper::getDemodulationLHSIterator(
Literal* lit, bool onlyPreordered, const Ordering& ord)
{
bool isPreordered = false;
if (lit->isEquality()) {
if (lit->isNegative()) {
return { VirtualIterator<TypedTermList>::getEmpty(), isPreordered };
}
TermList t0=*lit->nthArgument(0);
TermList t1=*lit->nthArgument(1);
switch(ord.getEqualityArgumentOrder(lit))
{
case Ordering::INCOMPARABLE:
if ( onlyPreordered ) {
return { VirtualIterator<TypedTermList>::getEmpty(), isPreordered };
}
if (t0.containsAllVariablesOf(t1)) {
if (t1.containsAllVariablesOf(t0)) {
if (MatchingUtils::matchReversedArgs(lit, lit)) {
return { withEqualitySort(lit, getSingletonIterator(t0) ), isPreordered };
}
return { withEqualitySort(lit, iterItems(t0, t1)), isPreordered };
}
return { withEqualitySort(lit, getSingletonIterator(t0) ), isPreordered };
}
if (t1.containsAllVariablesOf(t0)) {
return { withEqualitySort(lit, getSingletonIterator(t1) ), isPreordered };
}
break;
case Ordering::GREATER:
ASS(t0.containsAllVariablesOf(t1));
isPreordered = true;
return { withEqualitySort(lit, getSingletonIterator(t0) ), isPreordered };
case Ordering::LESS:
ASS(t1.containsAllVariablesOf(t0));
isPreordered = true;
return { withEqualitySort(lit, getSingletonIterator(t1) ), isPreordered };
case Ordering::EQUAL:
ASSERTION_VIOLATION_REP(*lit);
}
return { VirtualIterator<TypedTermList>::getEmpty(), isPreordered };
} else {
return { VirtualIterator<TypedTermList>::getEmpty(), isPreordered };
}
}
TermIterator EqHelper::getEqualityArgumentIterator(Literal* lit)
{
ASS(lit->isEquality());
return pvi( iterItems( *lit->nthArgument(0), *lit->nthArgument(1)) );
}
}