#ifndef __Term__
#define __Term__
#include "Forwards.hpp"
#include "Debug/Assertion.hpp"
#include "Lib/BitUtils.hpp"
#include "Lib/Metaiterators.hpp"
#include "Lib/Comparison.hpp"
#include "Lib/Reflection.hpp"
#include "Lib/Stack.hpp"
#include "Lib/Hash.hpp"
#include "Lib/Coproduct.hpp"
#include "Lib/Recycled.hpp"
#define TERM_DIST_VAR_BITS 19
#define TERM_DIST_VAR_UNKNOWN ((1 << TERM_DIST_VAR_BITS)-1)
namespace Kernel {
std::ostream& operator<<(std::ostream& out, Term const& self);
std::ostream& operator<<(std::ostream& out, TermList const& self);
std::ostream& operator<<(std::ostream& out, Literal const& self);
bool operator<(TermList const&,TermList const&);
using namespace Lib;
enum TermTag {
REF = 0u,
ORD_VAR = 1u,
FUN = 2u,
SPEC_VAR = 3u,
};
const unsigned TERM_TAG_BITS = 2;
static_assert(SPEC_VAR < 1 << TERM_TAG_BITS, "TermTag must fit within TERM_TAG_BITS");
enum ArgumentOrderVals {
AO_UNKNOWN=0,
AO_GREATER=1,
AO_LESS=2,
AO_EQUAL=3,
AO_INCOMPARABLE=4,
};
const unsigned ARGUMENT_ORDER_BITS = 3;
static_assert(AO_INCOMPARABLE < 1 << ARGUMENT_ORDER_BITS, "ArgumentOrderVals must fit within ARGUMENT_ORDER_BITS");
inline std::ostream& operator<<(std::ostream& out, ArgumentOrderVals const& self)
{
switch(self) {
case AO_UNKNOWN: return out << "UNKNOWN";
case AO_GREATER: return out << "GREATER";
case AO_LESS: return out << "LESS";
case AO_EQUAL: return out << "EQUAL";
case AO_INCOMPARABLE: return out << "INCOMPARABLE";
}
ASSERTION_VIOLATION
}
enum class TermKind : unsigned {
LITERAL,
TERM,
SORT,
};
struct SymbolId {
unsigned functor;
TermKind kind;
auto asTuple() const { return std::tie(functor, kind); }
IMPL_COMPARISONS_FROM_TUPLE(SymbolId);
};
struct VarNumber {
unsigned number;
bool special;
auto asTuple() const { return std::tie(number, special); }
IMPL_COMPARISONS_FROM_TUPLE(VarNumber);
};
enum class Proxy {
AND,
OR,
IMP,
FORALL,
EXISTS,
IFF,
XOR,
NOT,
PI,
SIGMA,
EQUALS,
NOT_PROXY
};
class TermList {
public:
TermList() : _content(FUN) {}
explicit TermList(const Term* t) : _content(0) {
_setTerm(t);
ASS_EQ(tag(), REF);
}
TermList(unsigned var, bool special)
{
if (special) {
makeSpecialVar(var);
}
else {
makeVar(var);
}
}
inline TermTag tag() const { return static_cast<TermTag>(_tag()); }
inline bool isEmpty() const
{ return tag() == FUN; }
inline bool isNonEmpty() const
{ return tag() != FUN; }
inline TermList* next()
{ return this-1; }
inline const TermList* next() const
{ return this-1; }
inline bool isVar() const { return tag() == ORD_VAR || tag() == SPEC_VAR; }
inline bool isOrdinaryVar() const { return tag() == ORD_VAR; }
inline bool isSpecialVar() const { return tag() == SPEC_VAR; }
inline unsigned var() const
{ ASS(isVar()); return _content / 4; }
inline bool isTerm() const
{ return tag() == REF; }
inline const Term* term() const
{ ASS(isTerm()); return _term(); }
inline Term* term()
{ ASS(isTerm()); return _term(); }
inline bool sameContent(const TermList* t) const
{ return _content == t->_content ; }
inline bool sameContent(const TermList& t) const
{ return sameContent(&t); }
inline uint64_t content() const { return _content; }
void setContent(uint64_t content) { _content = content; }
unsigned defaultHash() const { return DefaultHash::hash(content()); }
unsigned defaultHash2() const { return content(); }
std::string toString(bool needsPar = false) const;
friend std::ostream& operator<<(std::ostream& out, Kernel::TermList const& tl);
inline void makeVar(unsigned vnumber)
{ _content = vnumber * 4 + ORD_VAR; }
inline void makeSpecialVar(unsigned vnumber)
{ _content = vnumber * 4 + SPEC_VAR; }
inline static TermList empty()
{ return TermList(); }
class Top {
using Inner = Coproduct<VarNumber, SymbolId>;
Inner _inner;
Top(Inner self) : _inner(self) {}
public:
static Top var (unsigned v, bool special) { return Top(Inner(VarNumber {v, special})); }
template<class T>
static Top functor(T const* t) { return Top(Inner(SymbolId{ t->functor(), t->kind(), })); }
Option<VarNumber> var() const { return _inner.as<VarNumber>().toOwned(); }
Option<SymbolId> functor() const { return _inner.as<SymbolId>().toOwned(); }
Lib::Comparison compare(Top const& other) const
{ return _inner.compare(other._inner); }
IMPL_COMPARISONS_FROM_COMPARE(Top);
friend bool operator==(Top const& l, Top const& r) { return l._inner == r._inner; }
friend bool operator!=(Top const& l, Top const& r) { return !(l == r); }
void output(std::ostream& out) const;
friend std::ostream& operator<<(std::ostream& out, Kernel::TermList::Top const& self)
{ self.output(out); return out; }
};
Top top() const
{ return isTerm() ? TermList::Top::functor(term())
: TermList::Top::var(var(), isSpecialVar()); }
inline void setTerm(Term* t) {
_content = 0;
_setTerm(t);
ASS_EQ(tag(), REF);
}
static bool sameTop(TermList ss, TermList tt);
static bool sameTopFunctor(TermList ss, TermList tt);
static bool equals(TermList t1, TermList t2);
static bool allShared(TermList* args);
static TermList var(unsigned var, bool special = false) { return TermList(var, special); }
unsigned weight() const;
bool isArrowSort();
bool isBoolSort();
bool isArraySort();
bool isTupleSort();
bool containsSubterm(TermList v) const;
bool containsAllVariablesOf(TermList t) const;
bool ground() const;
bool isSafe() const;
bool isApplication() const;
bool isLambdaTerm() const;
bool isRedex() const;
bool isProxy(Proxy proxy) const;
bool isChoice() const;
Option<unsigned> deBruijnIndex() const;
TermList lhs() const;
TermList rhs() const;
TermList lambdaBody() const;
TermList head() const;
std::pair<TermList, TermList> asPair();
TermList domain();
TermList result();
TermList replaceSubterm(TermList what, TermList by, bool liftFreeIndices = false) const;
#if VDEBUG
void assertValid() const;
#endif
inline bool operator==(const TermList& t) const
{ return _content==t._content; }
inline bool operator!=(const TermList& t) const
{ return _content!=t._content; }
friend bool operator<(const TermList& lhs, const TermList& rhs);
private:
std::string asArgsToString() const;
#if 0#endif
uint64_t _content;
BITFIELD(64,
BITFIELD_MEMBER(uint32_t, _id, _setId, 32,
BITFIELD_MEMBER(uint32_t, _distinctVars, _setDistinctVars, TERM_DIST_VAR_BITS,
BITFIELD_MEMBER(unsigned, _order, _setOrder, ARGUMENT_ORDER_BITS,
BITFIELD_MEMBER(bool, _hasLambda, _setHasLambda, 1,
BITFIELD_MEMBER(bool, _hasRedex, _setHasRedex, 1,
BITFIELD_MEMBER(bool, _hasDeBruijnIndex, _setHasDeBruijnIndex, 1,
BITFIELD_MEMBER(bool, _hasTermVar, _setHasTermVar, 1,
BITFIELD_MEMBER(bool, _sort, _setSort, 1,
BITFIELD_MEMBER(bool, _literal, _setLiteral, 1,
BITFIELD_MEMBER(bool, _shared, _setShared, 1,
BITFIELD_MEMBER(bool, _polarity, _setPolarity, 1,
BITFIELD_MEMBER(unsigned, _tag, _setTag, TERM_TAG_BITS,
END_BITFIELD
)))))))))))))
BITFIELD_PTR_GET(Term, _term, 0)
BITFIELD_PTR_SET(Term, _setTerm, 0)
static_assert(sizeof(void *) <= sizeof(uint64_t), "must be able to fit a pointer into a 64-bit integer");
friend class Indexing::TermSharing;
friend class Term;
friend class Literal;
friend class AtomicSort;
}; static_assert(sizeof(TermList) == 8, "size of TermList must be exactly 64 bits");
enum class SpecialFunctor {
ITE,
LET,
FORMULA,
LAMBDA,
MATCH, };
static constexpr SpecialFunctor SPECIAL_FUNCTOR_LAST = SpecialFunctor::MATCH;
std::ostream& operator<<(std::ostream& out, SpecialFunctor const& self);
class alignas(8) Term
{
public:
static constexpr unsigned SPECIAL_FUNCTOR_LOWER_BOUND = std::numeric_limits<unsigned>::max() - unsigned(SPECIAL_FUNCTOR_LAST);
static SpecialFunctor toSpecialFunctor(unsigned f) {
ASS_GE(f, SPECIAL_FUNCTOR_LOWER_BOUND);
unsigned result = std::numeric_limits<unsigned>::max() - f;
ASS_LE(result, unsigned(SPECIAL_FUNCTOR_LAST))
return SpecialFunctor(result);
}
static unsigned toNormalFunctor(SpecialFunctor f)
{ return std::numeric_limits<unsigned>::max() - static_cast<unsigned>(f); }
class SpecialTermData
{
friend class Term;
private:
union {
struct {
Formula * condition;
TermList sort;
} _iteData;
struct {
Formula* binding;
TermList sort;
} _letData;
struct {
Formula * formula;
} _formulaData;
struct {
TermList lambdaExp;
VList* _vars;
SList* _sorts;
TermList sort;
TermList expSort; } _lambdaData;
struct {
TermList sort;
TermList matchedSort;
} _matchData;
};
const Term* getTerm() const { return reinterpret_cast<const Term*>(this+1); }
public:
SpecialFunctor specialFunctor() const
{ return getTerm()->specialFunctor(); }
Formula* getITECondition() const { ASS_EQ(specialFunctor(), SpecialFunctor::ITE); return _iteData.condition; }
VList* getLambdaVars() const { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); return _lambdaData._vars; }
void setLambdaVars(VList* vars) { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); _lambdaData._vars = vars; }
SList* getLambdaVarSorts() const { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); return _lambdaData._sorts; }
void setLambdaVarSorts(SList* sorts) { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); _lambdaData._sorts = sorts; }
TermList getLambdaExp() const { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); return _lambdaData.lambdaExp; }
void setLambdaExp(TermList exp) { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); _lambdaData.lambdaExp = exp; }
void setLambdaExpSort(TermList sort) { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); _lambdaData.expSort = sort; }
void setLambdaSort(TermList sort) { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); _lambdaData.sort = sort; }
Formula* getLetBinding() const { ASS_EQ(specialFunctor(), SpecialFunctor::LET); return _letData.binding; }
TermList getLambdaExpSort() const { ASS_EQ(specialFunctor(), SpecialFunctor::LAMBDA); return _lambdaData.expSort; }
TermList getSort() const {
switch (specialFunctor()) {
case SpecialFunctor::ITE:
return _iteData.sort;
case SpecialFunctor::LET:
return _letData.sort;
case SpecialFunctor::LAMBDA:
return _lambdaData.sort;
case SpecialFunctor::MATCH:
return _matchData.sort;
default:
ASSERTION_VIOLATION_REP(specialFunctor());
}
}
Formula* getFormula() const { ASS_EQ(specialFunctor(), SpecialFunctor::FORMULA); return _formulaData.formula; }
TermList getMatchedSort() const { return _matchData.matchedSort; }
};
Term() throw();
explicit Term(const Term& t) throw();
static Term* create(unsigned function, unsigned arity, const TermList* args);
static Term* create(unsigned fn, std::initializer_list<TermList> args);
static Term* create(unsigned fn, Stack<TermList> const& args) { return Term::create(fn, args.length(), args.begin()); }
template<class Iter>
static Term* createFromIter(unsigned fn, Iter args)
{
Recycled<Stack<TermList>> stack;
stack->loadFromIterator(args);
return Term::create(fn, *stack);
}
static Term* create(Term* t,TermList* args);
static Term* createNonShared(unsigned function, unsigned arity, TermList* arg);
static Term* createNonShared(Term* t,TermList* args);
static Term* createNonShared(Term* t);
static Term* cloneNonShared(Term* t);
static Term* createConstant(const std::string& name);
static Term* createConstant(unsigned symbolNumber) { return create(symbolNumber,0,0); }
static Term* createITE(Formula * condition, TermList thenBranch, TermList elseBranch, TermList branchSort);
static Term* createLet(Formula* binding, TermList body, TermList bodySort);
static Term* createLambda(TermList lambdaExp, VList* vars, SList* sorts, TermList expSort);
static Term* createFormula(Formula* formula);
static Term* createMatch(TermList sort, TermList matchedSort, unsigned int arity, TermList* elements);
static Term* create1(unsigned fn, TermList arg);
static Term* create2(unsigned fn, TermList arg1, TermList arg2);
static Term* foolTrue();
static Term* foolFalse();
static void resetStaticCaches();
size_t getPreDataSize() { return isSpecial() ? sizeof(SpecialTermData) : 0; }
const unsigned functor() const { return _functor; }
SpecialFunctor specialFunctor() const
{ return toSpecialFunctor(functor()); }
std::string toString(bool topLevel = true) const;
friend std::ostream& operator<<(std::ostream& out, Kernel::Term const& tl);
static std::string variableToString(unsigned var);
static std::string variableToString(TermList var);
const TermList* args() const
{ return _args + _arity; }
const TermList* nthArgument(int n) const
{
ASS(n >= 0);
ASS((unsigned)n < _arity);
return _args + (_arity - n);
}
TermList* nthArgument(int n)
{
ASS(n >= 0);
ASS((unsigned)n < _arity);
return _args + (_arity - n);
}
TermList termArg(unsigned n) const;
TermList typeArg(unsigned n) const;
unsigned numTypeArguments() const;
unsigned numTermArguments() const;
TermList* termArgs();
const TermList* typeArgs() const;
const TermList operator[](int i) const {
return *nthArgument(i);
}
TermList operator[](int i) {
return *nthArgument(i);
}
TermList* args()
{ return _args + _arity; }
template<class GetArg>
static unsigned termHash(unsigned functor, GetArg getArg, unsigned arity) {
return DefaultHash::hashIter(
range(0, arity).map([&](auto i) {
TermList t = getArg(i);
return DefaultHash::hashBytes(
reinterpret_cast<const unsigned char*>(&t),
sizeof(TermList)
);
}),
DefaultHash::hash(functor));
}
unsigned hash() const
{ return termHash(_functor, [&](auto i) { return *nthArgument(i); }, _arity); }
unsigned arity() const
{ return _arity; }
static void* operator new(size_t,unsigned arity,size_t preData=0);
void makeSymbol(unsigned number,unsigned arity)
{
_functor = number;
_arity = arity;
}
void destroy();
void destroyNonShared();
Term* apply(Substitution& subst);
bool allArgumentsAreVariables() const
{
for(unsigned i = 0; i < arity(); i++)
if(!nthArgument(i)->isVar())
return false;
return true;
}
bool ground() const
{
ASS(_args[0]._shared());
return numVarOccs() == 0;
}
bool hasTermVar() const
{
ASS(shared());
return _args[0]._hasTermVar();
}
bool shared() const
{ return _args[0]._shared(); }
unsigned weight() const
{
ASS(shared());
return _weight;
}
int maxRedLength() const
{
ASS(shared());
return _maxRedLen;
}
int kboWeight(const void* kboInstance) const
{
if (_kboEpoch != s_kboEpoch) return -1;
#if VDEBUG
ASS(_kboInstance && _kboInstance == kboInstance);
#endif
return _kboWeight;
}
void setKboWeight(int w, const void* kboInstance)
{
#if VDEBUG
ASS(!_kboInstance || _kboEpoch != s_kboEpoch);
_kboInstance = kboInstance;
#endif
_kboWeight = w;
_kboEpoch = s_kboEpoch;
}
static void invalidateKboWeightCache() { ++s_kboEpoch; }
void markShared()
{
ASS(! shared());
_args[0]._setShared(true);
}
void setWeight(unsigned w)
{
_weight = w;
}
void setId(unsigned id);
unsigned getId() const
{
ASS(shared());
return _args[0]._id();
}
void setMaxRedLen(int rl)
{
_maxRedLen = rl;
}
void setNumVarOccs(unsigned v)
{
if(_isTwoVarEquality) {
ASS_EQ(v,2);
return;
}
_vars = v;
}
void setHasTermVar(bool b)
{
ASS(shared() && !isSort())
_args[0]._setHasTermVar(b);
}
unsigned numVarOccs() const
{
ASS(shared());
if(_isTwoVarEquality) {
return _sort.isVar() ? 3 : 2 + _sort.term()->numVarOccs();
}
return _vars;
}
bool isTwoVarEquality() const
{
return _isTwoVarEquality;
}
const std::string& functionName() const;
bool isLiteral() const { return _args[0]._literal(); }
bool isSort() const { return _args[0]._sort(); }
bool isArrowSort() const;
TermKind kind() const { return isSort() ? TermKind::SORT
: isLiteral() ? TermKind::LITERAL
: TermKind::TERM; }
bool isApplication() const;
bool isLambdaTerm() const;
bool isRedex() const;
bool isProxy(Proxy proxy) const;
bool isChoice() const;
TermList lambdaBody() const {
ASS(isLambdaTerm())
return *nthArgument(2);
}
void setHasRedex(bool b) {
ASS(shared() && !isSort())
_args[0]._setHasRedex(b);
}
bool hasRedex() const {
ASS(shared())
return _args[0]._hasRedex();
}
Option<unsigned> deBruijnIndex() const;
void setHasDeBruijnIndex(bool b) {
ASS(shared() && !isSort());
_args[0]._setHasDeBruijnIndex(b);
}
bool hasDeBruijnIndex() const {
ASS(shared())
return _args[0]._hasDeBruijnIndex();
}
void setHasLambda(bool b) {
ASS(shared() && !isSort())
_args[0]._setHasLambda(b);
}
bool hasLambda() const {
ASS(shared())
return _args[0]._hasLambda();
}
unsigned getArgumentIndex(TermList* arg)
{
unsigned res=arity()-(arg-_args);
ASS_L(res,arity());
return res;
}
#if VDEBUG
std::string headerToString() const;
void assertValid() const;
#endif
static TermIterator getVariableIterator(TermList tl);
unsigned getDistinctVars()
{
if(_args[0]._distinctVars()==TERM_DIST_VAR_UNKNOWN) {
unsigned res=computeDistinctVars();
if(res<TERM_DIST_VAR_UNKNOWN) {
_args[0]._setDistinctVars(res);
}
return res;
} else {
ASS_L(_args[0]._distinctVars(),0x100000);
return _args[0]._distinctVars();
}
}
bool couldBeInstanceOf(Term* t)
{
ASS(shared());
ASS(t->shared());
if(t->functor()!=functor()) {
return false;
}
return true;
}
bool containsSubterm(TermList v) const;
bool containsAllVariablesOf(Term* t);
size_t countSubtermOccurrences(TermList subterm);
bool isShallow() const;
void setColor(Color color)
{
ASS(_color == static_cast<unsigned>(COLOR_TRANSPARENT) || _color == static_cast<unsigned>(color));
_color = color;
}
Color color() const { return static_cast<Color>(_color); }
bool skip() const;
bool hasInterpretedConstants() const { return _hasInterpretedConstants; }
void setInterpretedConstantsPresence(bool value) { _hasInterpretedConstants=value; }
bool isSpecial() const { return functor() >= SPECIAL_FUNCTOR_LOWER_BOUND; }
bool isITE() const { return functor() == toNormalFunctor(SpecialFunctor::ITE); }
bool isLet() const { return functor() == toNormalFunctor(SpecialFunctor::LET); }
bool isFormula() const { return functor() == toNormalFunctor(SpecialFunctor::FORMULA); }
bool isLambda() const { return functor() == toNormalFunctor(SpecialFunctor::LAMBDA); }
bool isMatch() const { return functor() == toNormalFunctor(SpecialFunctor::MATCH); }
bool isBoolean() const;
bool isSuper() const;
const SpecialTermData* getSpecialData() const { return const_cast<Term*>(this)->getSpecialData(); }
SpecialTermData* getSpecialData() {
ASS(isSpecial());
return reinterpret_cast<SpecialTermData*>(this)-1;
}
protected:
std::string headToString() const;
unsigned computeDistinctVars() const;
ArgumentOrderVals getArgumentOrderValue() const
{
return static_cast<ArgumentOrderVals>(_args[0]._order());
}
void setArgumentOrderValue(ArgumentOrderVals val)
{
ASS_GE(val,AO_UNKNOWN);
ASS_LE(val,AO_INCOMPARABLE);
_args[0]._setOrder(val);
}
unsigned _functor;
unsigned _arity : 28;
unsigned _color : 2;
unsigned _hasInterpretedConstants : 1;
unsigned _isTwoVarEquality : 1;
unsigned _weight;
int _kboWeight;
unsigned _kboEpoch;
#if VDEBUG
const void* _kboInstance;
#endif
int _maxRedLen;
union {
unsigned _vars;
TermList _sort;
};
TermList _args[1];
friend class TermList;
friend class Indexing::TermSharing;
friend class Ordering;
static unsigned s_kboEpoch;
public:
class Iterator
{
public:
DECL_ELEMENT_TYPE(TermList);
Iterator(const Term* t) : _next(t->args()) {}
bool hasNext() const { return _next->isNonEmpty(); }
TermList next()
{
ASS(hasNext());
TermList res = *_next;
_next = _next->next();
return res;
}
private:
const TermList* _next;
}; };
class AtomicSort
: public Term
{
public:
AtomicSort();
explicit AtomicSort(const AtomicSort& t) throw();
AtomicSort(unsigned functor,unsigned arity) throw()
{
_functor = functor;
_arity = arity;
_args[0]._setLiteral(false);
_args[0]._setSort(true);
}
static AtomicSort* create(unsigned typeCon, unsigned arity, const TermList* args);
static AtomicSort* create2(unsigned tc, TermList arg1, TermList arg2);
static AtomicSort* create(AtomicSort const* t,TermList* args);
static AtomicSort* createNonShared(AtomicSort const* sort,TermList* args);
static AtomicSort* createConstant(unsigned typeCon) { return create(typeCon,0,0); }
static AtomicSort* createConstant(const std::string& name);
bool isArrowSort() const;
bool isBoolSort() const;
bool isArraySort() const;
bool isTupleSort() const;
const std::string& typeConName() const;
static TermList arrowSort(const TermStack& domSorts, TermList range);
static TermList arrowSort(TermList s1, TermList s2);
static TermList arrowSort(TermList s1, TermList s2, TermList s3);
static TermList arrowSort(unsigned size, const TermList* types, TermList range);
static TermList arraySort(TermList indexSort, TermList innerSort);
static TermList tupleSort(unsigned arity, TermList* sorts);
static TermList defaultSort();
static TermList superSort();
static TermList boolSort();
static TermList intSort();
static TermList realSort();
static TermList rationalSort();
static void resetStaticCaches();
private:
static AtomicSort* createNonShared(unsigned typeCon, unsigned arity, TermList* arg);
static AtomicSort* createNonSharedConstant(unsigned typeCon) { return createNonShared(typeCon,0,0); }
};
class Literal
: public Term
{
public:
bool isEquality() const
{ return functor() == 0; }
Literal();
explicit Literal(const Literal& l) throw();
Literal(unsigned functor,unsigned arity,bool polarity) throw()
{
_functor = functor;
_arity = arity;
_args[0]._setPolarity(polarity);
_args[0]._setSort(false);
_args[0]._setLiteral(true);
}
unsigned header() const
{ return 2*_functor + polarity(); }
unsigned complementaryHeader() const
{ return 2*_functor + 1 - polarity(); }
static bool headersMatch(Literal* l1, Literal* l2, bool complementary);
void setPolarity(bool positive)
{ _args[0]._setPolarity(positive); }
TermList eqArgSort() const;
template<class Iter> static Literal* createFromIter(unsigned predicate, unsigned polarity, Iter iter) = delete;
template<class Iter> static Literal* createFromIter( bool predicate, unsigned polarity, Iter iter) = delete;
template<class Iter> static Literal* createFromIter( bool predicate, bool polarity, Iter iter) = delete;
template<class Iter>
static Literal* createFromIter(unsigned predicate, bool polarity, Iter iter) {
RStack<TermList> args;
while (iter.hasNext()) {
args->push(iter.next());
}
return Literal::create(predicate, args->size(), polarity, args->begin());
}
template<class Iter>
static Literal* createFromIter(Literal* lit, Iter iter) {
if (lit->isEquality()) {
return Literal::createEquality(lit->polarity(), iter.tryNext().unwrap(), iter.tryNext().unwrap(), lit->eqArgSort());
} else {
return Literal::createFromIter(lit->functor(), bool(lit->polarity()), std::move(iter));
}
}
static Literal* create(unsigned predicate, unsigned arity, bool polarity, TermList* args);
static Literal* create(unsigned predicate, bool polarity, std::initializer_list<TermList>);
static Literal* create(Literal* l,bool polarity);
static Literal* create(Literal* l,TermList* args);
static Literal* createEquality(bool polarity, TermList arg1, TermList arg2, TermList sort);
static Literal* create1(unsigned predicate, bool polarity, TermList arg);
static Literal* create2(unsigned predicate, bool polarity, TermList arg1, TermList arg2);
template<bool flip = false>
unsigned hash() const
{
return Literal::literalHash(functor(), polarity() ^ flip,
[&](auto i) -> TermList const& { return *nthArgument(i); }, arity(),
someIf(isTwoVarEquality(), [&](){ return twoVarEqSort(); }));
}
template<class GetArg>
static unsigned literalEquals(const Literal* lit, unsigned functor, bool polarity, GetArg getArg, unsigned arity, Option<TermList> twoVarEqSort) {
if (functor != lit->functor() || polarity != lit->polarity()) return false;
if (functor == 0) { ASS_EQ(arity, 2)
ASS(rightArgOrder(getArg(0), getArg(1)))
ASS(rightArgOrder(*lit->nthArgument(0), *lit->nthArgument(1)))
if (someIf(lit->isTwoVarEquality(), [&](){ return lit->twoVarEqSort(); }) != twoVarEqSort) {
return false;
}
return std::make_tuple(*lit->nthArgument(0), *lit->nthArgument(1)) == std::make_tuple(getArg(0), getArg(1));
} else {
ASS(twoVarEqSort.isNone())
return range(0, arity).all([&](auto i) { return *lit->nthArgument(i) == getArg(i); });
}
}
static bool rightArgOrder(TermList const& lhs, TermList const& rhs);
template<class GetArg>
static unsigned literalHash(unsigned functor, bool polarity, GetArg getArg, unsigned arity, Option<TermList> twoVarEqSort) {
if (functor == 0) { ASS_EQ(arity, 2)
ASS(rightArgOrder(getArg(0), getArg(1)))
return HashUtils::combine(
DefaultHash::hash(polarity),
DefaultHash::hash(functor),
DefaultHash::hash(twoVarEqSort),
getArg(0).defaultHash(),
getArg(1).defaultHash());
} else {
ASS(twoVarEqSort.isNone())
return HashUtils::combine(
DefaultHash::hash(polarity),
Term::termHash(functor, getArg, arity));
}
}
static Literal* complementaryLiteral(Literal* l);
static Literal* positiveLiteral(Literal* l) {
return l->isPositive() ? l : complementaryLiteral(l);
}
void argSwap() {
ASS(isEquality() && !shared());
ASS(arity() == 2);
TermList* ts1 = args();
TermList* ts2 = ts1->next();
using std::swap; swap(ts1->_content, ts2->_content);
}
bool isPositive() const
{
return polarity();
}
bool isNegative() const
{
return !polarity();
}
int polarity() const
{
return _args[0]._polarity();
}
void markTwoVarEquality()
{
ASS(!shared());
ASS(isEquality());
ASS(nthArgument(0)->isVar() || !nthArgument(0)->term()->shared());
ASS(nthArgument(1)->isVar() || !nthArgument(1)->term()->shared());
_isTwoVarEquality = true;
}
TermList twoVarEqSort() const
{
ASS(isTwoVarEquality());
return _sort;
}
void setTwoVarEqSort(TermList sort)
{
ASS(isTwoVarEquality());
_sort = sort;
}
Literal* apply(Substitution& subst);
inline bool couldBeInstanceOf(Literal* lit, bool complementary)
{
ASS(shared());
ASS(lit->shared());
return headersMatch(this, lit, complementary);
}
bool isAnswerLiteral() const;
friend std::ostream& operator<<(std::ostream& out, Kernel::Literal const& tl);
std::string toString(bool reverseEquality = false) const;
const std::string& predicateName() const;
private:
template<class GetArg>
static Literal* create(unsigned predicate, unsigned arity, bool polarity, GetArg args, Option<TermList> twoVarEqSort = Option<TermList>());
};
bool positionIn(TermList& subterm,TermList* term, std::string& position);
bool positionIn(TermList& subterm,Term* term, std::string& position);
struct SharedTermHash {
static bool equals(Term* t1, Term* t2) { return t1==t2; }
static unsigned hash(Term* t) { return t->getId(); }
};
static const auto unsignedToVarFn = [](unsigned var)
{ return TermList::var(var); };
}
template<>
struct std::hash<Kernel::TermList> {
size_t operator()(Kernel::TermList const& t) const
{ return t.defaultHash(); }
};
#endif