#ifndef __Formula__
#define __Formula__
#include "Forwards.hpp"
#include "Kernel/Signature.hpp"
#include "Kernel/SortHelper.hpp"
#include "Connective.hpp"
#include "Term.hpp"
namespace Kernel {
using namespace Lib;
class Formula
{
public:
explicit Formula (bool value)
: _connective(value ? TRUE : FALSE)
{
}
Connective connective () const { return _connective; }
const FormulaList* args() const;
FormulaList* args();
FormulaList** argsPtr();
const Formula* left() const;
Formula* left();
const Formula* right() const;
Formula* right();
void leftRightSwap();
const Formula* qarg() const;
Formula* qarg();
const VList* vars() const;
VList* vars();
VList** varsPtr();
const SList* sorts() const;
SList* sorts();
SList** sortsPtr();
const Formula* uarg() const;
Formula* uarg();
const Literal* literal() const;
Literal* literal();
const TermList getBooleanTerm() const;
TermList getBooleanTerm();
VList* boundVariables () const;
std::string toString() const;
static std::string toString(Connective con);
bool parenthesesRequired(Connective outer) const;
void destroy();
unsigned weight() const;
Color getColor();
bool getSkip();
bool hasLabel(){ return _label != DEFAULT_LABEL; }
std::string getLabel(){ return _label;}
void label(std::string l){ _label=l; }
static Formula* fromClause(Clause* cl,bool closed = true);
static Formula* quantify(Formula* f);
static Formula* trueFormula();
static Formula* falseFormula();
static Formula* createITE(Formula* condition, Formula* thenArg, Formula* elseArg);
static Formula* createLet(Formula* binder, Formula* body);
static Formula* createDefinition(Term* lhs, TermList rhs, VList* uVars = VList::empty());
USE_ALLOCATOR(Formula);
protected:
explicit Formula(Connective con)
: _connective(con), _label(DEFAULT_LABEL)
{}
Connective _connective;
static std::string DEFAULT_LABEL;
std::string _label;
};
class NamedFormula
: public Formula
{
public:
explicit NamedFormula(std::string name) : Formula(NAME), _name(name) {}
USE_ALLOCATOR(NamedFormula);
std::string name(){ return _name; }
const std::string name() const { return _name;}
protected:
std::string _name;
};
class AtomicFormula
: public Formula
{
public:
explicit AtomicFormula (Literal* lit, bool flipForPrinting = false)
: Formula(LITERAL),
flipForPrinting(flipForPrinting),
_literal(lit) {}
const Literal* getLiteral() const { return _literal; }
Literal* getLiteral() { return _literal; }
void setLiteral(Literal* lit) { _literal = lit; }
USE_ALLOCATOR(AtomicFormula);
bool flipForPrinting = false;
protected:
Literal* _literal;
};
class QuantifiedFormula
: public Formula
{
public:
QuantifiedFormula(Connective con, VList* vs, SList* ss, Formula* arg)
: Formula(con),
_vars(vs),
_sorts(ss),
_arg(arg)
{
ASS(con == FORALL || con == EXISTS);
ASS(vs);
ASS(!ss || VList::length(vs) == SList::length(ss));
}
const Formula* subformula () const { return _arg; }
Formula* subformula () { return _arg; }
const VList* varList() const { return _vars; }
VList* varList() { return _vars; }
VList** varListPtr() { return &_vars; }
const SList* sortList() const { return _sorts; }
SList* sortList() { return _sorts; }
SList** sortListPtr() { return &_sorts; }
USE_ALLOCATOR(QuantifiedFormula);
protected:
VList* _vars;
SList* _sorts;
Formula* _arg;
};
class NegatedFormula
: public Formula
{
public:
explicit NegatedFormula (Formula* f)
: Formula(NOT),
_arg(f)
{}
const Formula* subformula() const { return _arg; }
Formula* subformula() { return _arg; }
USE_ALLOCATOR(NegatedFormula);
protected:
Formula* _arg;
};
class BinaryFormula
: public Formula
{
public:
explicit BinaryFormula (Connective con,Formula* lhs,Formula* rhs)
: Formula(con),
_left(lhs),
_right(rhs)
{
ASS(con == IFF || con == XOR || con == IMP);
}
const Formula* lhs() const { return _left; }
Formula* lhs() { return _left; }
const Formula* rhs() const { return _right; }
Formula* rhs() { return _right; }
void swapLeftRight() {
std::swap(_left,_right);
}
USE_ALLOCATOR(BinaryFormula);
protected:
Formula* _left;
Formula* _right;
};
class JunctionFormula
: public Formula
{
public:
JunctionFormula (Connective con, FormulaList* args)
: Formula(con),
_args(args)
{
ASS(con == AND || con == OR);
ASS_GE(FormulaList::length(args),2);
}
void setArgs(FormulaList* args) { _args = args; }
const FormulaList* getArgs() const { return _args; }
FormulaList* getArgs() { return _args; }
FormulaList** getArgsPtr() { return &_args; }
static Formula* generalJunction(Connective c, FormulaList* args);
USE_ALLOCATOR(JunctionFormula);
protected:
FormulaList* _args;
};
class BoolTermFormula
: public Formula
{
public:
BoolTermFormula (TermList ts)
: Formula(BOOL_TERM),
_ts(ts)
{
ASS_REP(ts.isVar() ||
(!ts.term()->isSpecial() && SortHelper::getResultSort(ts.term()) == AtomicSort::boolSort()) ||
(ts.term()->isSpecial() && !ts.term()->isFormula() && ts.term()->getSpecialData()->getSort() == AtomicSort::boolSort()), ts.toString());
}
static Formula* create(TermList ts);
const TermList getTerm() const { return _ts; }
TermList getTerm() { return _ts; }
USE_ALLOCATOR(BoolTermFormula);
protected:
TermList _ts;
};
inline
const VList* Formula::vars() const
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<const QuantifiedFormula*>(this)->varList();
}
inline
VList* Formula::vars()
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<QuantifiedFormula*>(this)->varList();
}
inline
VList** Formula::varsPtr()
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<QuantifiedFormula*>(this)->varListPtr();
}
inline
const SList* Formula::sorts() const
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<const QuantifiedFormula*>(this)->sortList();
}
inline
SList* Formula::sorts()
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<QuantifiedFormula*>(this)->sortList();
}
inline
SList** Formula::sortsPtr()
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<QuantifiedFormula*>(this)->sortListPtr();
}
inline
const Formula* Formula::qarg() const
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<const QuantifiedFormula*>(this)->subformula();
}
inline
Formula* Formula::qarg()
{
ASS(_connective == FORALL || _connective == EXISTS);
return static_cast<QuantifiedFormula*>(this)->subformula();
}
inline
const Formula* Formula::uarg() const
{
ASS(_connective == NOT);
return static_cast<const NegatedFormula*>(this)->subformula();
}
inline
Formula* Formula::uarg()
{
ASS(_connective == NOT);
return static_cast<NegatedFormula*>(this)->subformula();
}
inline
const FormulaList* Formula::args() const
{
ASS(_connective == AND || _connective == OR);
return static_cast<const JunctionFormula*>(this)->getArgs();
}
inline
FormulaList* Formula::args()
{
ASS(_connective == AND || _connective == OR);
return static_cast<JunctionFormula*>(this)->getArgs();
}
inline
FormulaList** Formula::argsPtr()
{
ASS(_connective == AND || _connective == OR);
return static_cast<JunctionFormula*>(this)->getArgsPtr();
}
inline
const Literal* Formula::literal() const
{
ASS(_connective == LITERAL);
return static_cast<const AtomicFormula*>(this)->getLiteral();
}
inline
Literal* Formula::literal()
{
ASS(_connective == LITERAL);
return static_cast<AtomicFormula*>(this)->getLiteral();
}
inline
const Formula* Formula::left() const
{
ASS(_connective == IFF || _connective == XOR || _connective == IMP);
return static_cast<const BinaryFormula*>(this)->lhs();
}
inline
Formula* Formula::left()
{
ASS(_connective == IFF || _connective == XOR || _connective == IMP);
return static_cast<BinaryFormula*>(this)->lhs();
}
inline void Formula::leftRightSwap()
{
ASS(_connective == IFF || _connective == XOR || _connective == IMP);
return static_cast<BinaryFormula*>(this)->swapLeftRight();
}
inline
const Formula* Formula::right() const
{
ASS(_connective == IFF || _connective == XOR || _connective == IMP);
return static_cast<const BinaryFormula*>(this)->rhs();
}
inline
Formula* Formula::right()
{
ASS(_connective == IFF || _connective == XOR || _connective == IMP);
return static_cast<BinaryFormula*>(this)->rhs();
}
inline
const TermList Formula::getBooleanTerm() const
{
ASS(_connective == BOOL_TERM);
return static_cast<const BoolTermFormula*>(this)->getTerm();
}
inline
TermList Formula::getBooleanTerm()
{
ASS(_connective == BOOL_TERM);
return static_cast<BoolTermFormula*>(this)->getTerm();
}
std::ostream& operator<< (std::ostream& out, const Formula& f);
std::ostream& operator<< (std::ostream& out, const Formula* f);
}
#endif