##
# Check the existence of the ANTLR3 C runtime library and headers
-# Will set ANTLR_INCLUDES and ANTLR_LIBS to the location of the ANTLR headers
-# and library respectively
+# Will set ANTLR_INCLUDES and ANTLR_LIBS to the location of the ANTLR
+# headers and library respectively
##
AC_DEFUN([AC_LIB_ANTLR],[
+ AC_ARG_VAR(ANTLR_HOME, [path to libantlr3c installation])
# Get the location of the ANTLR3 C includes and libraries
AC_ARG_WITH(
CFLAGS="${CFLAGS:+$CFLAGS }$CVC4CFLAGS -Wno-deprecated"
LDFLAGS="${LDFLAGS:+$LDFLAGS }$CVC4LDFLAGS"
+FLAG_VISIBILITY_HIDDEN='-fvisibility=hidden'
+AC_SUBST(FLAG_VISIBILITY_HIDDEN)
+
# mk_include
#
# When automake scans Makefiles, it complains about non-standard make
AM_CPPFLAGS =
-D__BUILDING_CVC4LIB \
-I@srcdir@/include -I@srcdir@
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
SUBDIRS = expr util context theory prop smt . parser main
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../include -I@srcdir@/..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libcontext.la
for(typename std::vector<Element*>::iterator i = d_trash.begin();
i != d_trash.end();
++i) {
- (*i)->deleteSelf();
+ Debug("gc") << "emptyTrash(): " << *i << std::endl;
+ //(*i)->deleteSelf();
}
d_trash.clear();
}
/**
* Get the level of the current Scope
*/
- int getLevel(void) const { return d_level; }
+ int getLevel() const { return d_level; }
/**
* Return true iff this Scope is the current top Scope
*/
- bool isCurrent(void) const { return this == d_pContext->getTopScope(); }
+ bool isCurrent() const { return this == d_pContext->getTopScope(); }
/**
* When a ContextObj object is modified for the first time in this Scope, it
static void operator delete(void* pMem) {}
//FIXME: //! Check for memory leaks
- // void check(void);
+ // void check();
};/* class Scope */
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../include -I@srcdir@/..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libexpr.la
// individual MetaKind constants under kind::metakind::
typedef ::CVC4::kind::metakind::MetaKind_t MetaKind;
+/**
+ * Get the metakind for a particular kind.
+ */
static inline MetaKind metaKindOf(Kind k) {
static const MetaKind metaKinds[] = {
metakind::INVALID, /* NULL_EXPR */
return metaKinds[k];
}/* metaKindOf(k) */
-static inline bool kindIsAtomic(Kind k) {
- static const bool isAtomic[] = {
+/**
+ * Determine if a particular kind can be atomic or not. Some kinds
+ * are never atomic (OR, NOT, ITE...), some can be atomic depending on
+ * their children (PLUS might have an ITE under it, for instance).
+ */
+static inline bool kindCanBeAtomic(Kind k) {
+ static const bool canBeAtomic[] = {
false, /* NULL_EXPR */
-${metakind_isatomic}
+${metakind_canbeatomic}
false /* LAST_KIND */
- };/* isAtomic[] */
+ };/* canBeAtomic[] */
- return isAtomic[k];
-}/* kindIsAtomic(k) */
+ return canBeAtomic[k];
+}/* kindCanBeAtomic(k) */
}/* CVC4::kind namespace */
** for the CVC4 project.
**/
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT ! */
+
+/* Edit the template file instead: */
+/* $1 */
+
EOF
me=$(basename "$0")
nc=$3
if [ $mk = NONATOMIC_OPERATOR ]; then
- metakind_isatomic="${metakind_isatomic} false, /* $k */
+ metakind_canbeatomic="${metakind_canbeatomic} false, /* $k */
";
mk=OPERATOR
else
- metakind_isatomic="${metakind_isatomic} true, /* $k */
+ metakind_canbeatomic="${metakind_canbeatomic} true, /* $k */
";
fi
metakind_kinds="${metakind_kinds}
/* from $b */
"
- metakind_isatomic="${metakind_isatomic}
+ metakind_canbeatomic="${metakind_canbeatomic}
/* from $b */
"
source "$kf"
for var in \
metakind_includes \
metakind_kinds \
- metakind_isatomic \
+ metakind_canbeatomic \
metakind_constantMaps \
metakind_compares \
metakind_constHashes \
NodeTemplate<ref_count> NodeTemplate<ref_count>::s_null(&expr::NodeValue::s_null);
template <bool ref_count>
-bool NodeTemplate<ref_count>::isAtomic() const {
- return kind::kindIsAtomic(getKind());
+inline bool NodeTemplate<ref_count>::isAtomic() const {
+ return NodeManager::currentNM()->isAtomic(*this);
}
// FIXME: escape from type system convenient but is there a better
namespace CVC4 {
-class Type;
-
namespace expr {
-namespace attr {
-
-struct VarName {};
-struct Type {};
+// Definition of an attribute for the variable name.
+// TODO: hide this attribute behind a NodeManager interface.
+namespace attr {
+ struct VarNameTag {};
}/* CVC4::expr::attr namespace */
-typedef Attribute<attr::VarName, std::string> VarNameAttr;
-typedef ManagedAttribute<attr::Type, CVC4::Type*, attr::TypeCleanupStrategy> TypeAttr;
+typedef expr::Attribute<attr::VarNameTag, std::string> VarNameAttr;
}/* CVC4::expr namespace */
expr::NodeValue* child[N];
};/* struct NodeManager::NVStorage<N> */
+ // attribute tags
+ struct TypeTag {};
+ struct AtomicTag {};
+
+ // NodeManager's attributes. These aren't exposed outside of this
+ // class; use the getters.
+ typedef expr::ManagedAttribute<TypeTag,
+ CVC4::Type*,
+ expr::attr::TypeCleanupStrategy> TypeAttr;
+ typedef expr::Attribute<AtomicTag, bool> AtomicAttr;
+
+ /**
+ * Returns true if this node is atomic (has no more Boolean
+ * structure). This is the NodeValue version for NodeManager's
+ * internal use. There's a public version of this function below
+ * that takes a TNode.
+ * @param nv the node to check for atomicity
+ * @return true if atomic
+ */
+ inline bool isAtomic(expr::NodeValue* nv) const {
+ // The kindCanBeAtomic() and metakind checking are just optimizations
+ // (to avoid the hashtable lookup). We assume that all nodes have
+ // the atomic attribute pre-computed and set at their time of
+ // creation. This is because:
+ // (1) it's super cheap to do it bottom-up.
+ // (2) if we computed it lazily, we'd need a second attribute to
+ // tell us whether we had computed it yet or not.
+ // The pre-computation and registration occurs in poolInsert().
+ AssertArgument(nv->getMetaKind() != kind::metakind::INVALID, *nv,
+ "NodeManager::isAtomic() called on INVALID node (%s)",
+ kind::kindToString(nv->getKind()).c_str());
+ return
+ nv->getMetaKind() == kind::metakind::VARIABLE ||
+ nv->getMetaKind() == kind::metakind::CONSTANT ||
+ ( kind::kindCanBeAtomic(nv->getKind()) &&
+ getAttribute(nv, AtomicAttr()) );
+ }
+
public:
NodeManager(context::Context* ctxt);
* TODO: Does this call compute the type if it's not already available?
*/
inline Type* getType(TNode n) const;
+
+ /**
+ * Returns true if this node is atomic (has no more Boolean structure)
+ * @param n the node to check for atomicity
+ * @return true if atomic
+ */
+ inline bool isAtomic(TNode n) const {
+ return isAtomic(n.d_nv);
+ }
};
/**
}
inline Type* NodeManager::getType(TNode n) const {
- return getAttribute(n, CVC4::expr::TypeAttr());
+ return getAttribute(n, TypeAttr());
}
inline expr::NodeValue* NodeManager::poolLookup(expr::NodeValue* nv) const {
Assert(d_nodeValuePool.find(nv) == d_nodeValuePool.end(),
"NodeValue already in the pool!");
d_nodeValuePool.insert(nv);// FIXME multithreading
+
+ switch(nv->getMetaKind()) {
+ case kind::metakind::INVALID:
+ case kind::metakind::VARIABLE:
+ case kind::metakind::CONSTANT:
+ // nothing to do (don't bother setting the attribute, isAtomic()
+ // on VARIABLEs and CONSTANTs is always true)
+ break;
+
+ case kind::metakind::OPERATOR:
+ case kind::metakind::PARAMETERIZED:
+ {
+ // register this NodeValue as atomic or not; use nv_begin/end
+ // because we need to consider the operator too in the case of
+ // PARAMETERIZED-metakinded nodes (i.e. APPLYs); they could have a
+ // buried ITE.
+
+ // assume it's atomic if its kind can be atomic, check children
+ // to see if that is actually true
+ bool atomic = kind::kindCanBeAtomic(nv->getKind());
+ if(atomic) {
+ for(expr::NodeValue::nv_iterator i = nv->nv_begin();
+ i != nv->nv_end();
+ ++i) {
+ if(!(atomic = isAtomic(*i))) {
+ break;
+ }
+ }
+ }
+
+ setAttribute(nv, AtomicAttr(), atomic);
+ }
+ }
}
inline void NodeManager::poolRemove(expr::NodeValue* nv) {
inline Node NodeManager::mkVar(Type* type) {
Node n = mkVar();
type->inc();// reference-count the type
- n.setAttribute(expr::TypeAttr(), type);
+ n.setAttribute(TypeAttr(), type);
return n;
}
}
cerr << "CVC4 Error:" << endl << e << endl;
printf(usage, options.binary_name.c_str());
- abort();
+ exit(1);
} catch(Exception& e) {
if(options.smtcomp_mode) {
cout << "unknown" << endl;
}
cerr << "CVC4 Error:" << endl << e << endl;
- abort();
+ exit(1);
} catch(bad_alloc) {
if(options.smtcomp_mode) {
cout << "unknown" << endl;
}
cerr << "CVC4 ran out of memory." << endl;
- abort();
+ exit(1);
} catch(...) {
if(options.smtcomp_mode) {
cout << "unknown" << endl;
}
cerr << "CVC4 threw an exception of unknown type." << endl;
- abort();
+ exit(1);
}
}
AM_CPPFLAGS = \
-D__BUILDING_CVC4PARSERLIB \
-I@srcdir@/../include -I@srcdir@/.. $(ANTLR_INCLUDES)
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
SUBDIRS = smt cvc
static pANTLR3_COMMON_TOKEN
LB(pANTLR3_COMMON_TOKEN_STREAM cts, ANTLR3_INT32 k)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_COMMON_TOKEN
get (pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 i)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_TOKEN_SOURCE
static pANTLR3_STRING
toString (pANTLR3_TOKEN_STREAM ts)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_STRING
toStringSS(pANTLR3_TOKEN_STREAM ts, ANTLR3_UINT32 start, ANTLR3_UINT32 stop)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_STRING
toStringTT (pANTLR3_TOKEN_STREAM ts, pANTLR3_COMMON_TOKEN start, pANTLR3_COMMON_TOKEN stop)
{
- AlwaysAssert(false);
+ Unreachable();
}
/** Move the input pointer to the next incoming token. The stream
static pANTLR3_VECTOR
getTokens (pANTLR3_COMMON_TOKEN_STREAM tokenStream)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_LIST
getTokenRange (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop)
{
- AlwaysAssert(false);
+ Unreachable();
}
/** Given a start and stop index, return a List of all tokens in
* the token type BitSet. Return null if no tokens were found. This
static pANTLR3_LIST
getTokensSet (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_BITSET types)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_LIST
getTokensList (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, pANTLR3_LIST list)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_LIST
getTokensType (pANTLR3_COMMON_TOKEN_STREAM tokenStream, ANTLR3_UINT32 start, ANTLR3_UINT32 stop, ANTLR3_UINT32 type)
{
- AlwaysAssert(false);
+ Unreachable();
}
static ANTLR3_UINT32
static ANTLR3_UINT32
dbgLA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)
{
- AlwaysAssert(false);
+ Unreachable();
}
static ANTLR3_MARKER
mark (pANTLR3_INT_STREAM is)
{
- AlwaysAssert(false);
+ Unreachable();
}
/// As per mark() but with a call to tell the debugger we are doing this
static ANTLR3_MARKER
dbgMark (pANTLR3_INT_STREAM is)
{
- AlwaysAssert(false);
+ Unreachable();
}
static void
static ANTLR3_UINT32
size (pANTLR3_INT_STREAM is)
{
- AlwaysAssert(false);
+ Unreachable();
}
static ANTLR3_MARKER
static void
dbgRewindLast (pANTLR3_INT_STREAM is)
{
- AlwaysAssert(false);
+ Unreachable();
}
static void
rewindLast (pANTLR3_INT_STREAM is)
{
- AlwaysAssert(false);
+ Unreachable();
}
static void
rewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
{
- AlwaysAssert(false);
+ Unreachable();
}
static void
dbgRewindStream (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)
{
- AlwaysAssert(false);
+ Unreachable();
}
static void
seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
{
- AlwaysAssert(false);
+ Unreachable();
}
static void
dbgSeek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)
{
- AlwaysAssert(false);
+ Unreachable();
}
static pANTLR3_COMMON_TOKEN nextToken(pBOUNDED_TOKEN_BUFFER buffer) {
AM_CPPFLAGS = \
-D__BUILDING_CVC4PARSERLIB \
-I@srcdir@/../../include -I@srcdir@/../.. $(ANTLR_INCLUDES)
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
# Compile generated C files using C++ compiler
CC=$(CXX)
AM_CPPFLAGS = \
-D__BUILDING_CVC4PARSERLIB \
-I@srcdir@/../../include -I@srcdir@/../.. $(ANTLR_INCLUDES)
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
# Compile generated C files using C++ compiler
AM_CFLAGS = $(AM_CXXFLAGS)
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../include -I@srcdir@/..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libprop.la
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/mtl -I@srcdir@/core -I@srcdir@/../.. -I@srcdir@/../../include
-AM_CXXFLAGS = -Wall -fvisibility=hidden -DNDEBUG
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN) -DNDEBUG
noinst_LTLIBRARIES = libminisat.la
libminisat_la_SOURCES = \
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../include -I@srcdir@/..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libsmt.la
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../include -I@srcdir@/..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libtheory.la
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../../include -I@srcdir@/../..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libarith.la
libarith_la_SOURCES = \
- theory_def.h \
theory_arith.h
EXTRA_DIST = kinds
namespace theory {
namespace arith {
-class TheoryArith : public TheoryImpl<TheoryArith> {
+class TheoryArith : public Theory {
public:
TheoryArith(context::Context* c, OutputChannel& out) :
- TheoryImpl<TheoryArith>(c, out) {
+ Theory(c, out) {
}
void preRegisterTerm(TNode n) { Unimplemented(); }
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../../include -I@srcdir@/../..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libarrays.la
libarrays_la_SOURCES = \
- theory_def.h \
theory_arrays.h
EXTRA_DIST = kinds
namespace theory {
namespace arrays {
-class TheoryArrays : public TheoryImpl<TheoryArrays> {
+class TheoryArrays : public Theory {
public:
TheoryArrays(context::Context* c, OutputChannel& out) :
- TheoryImpl<TheoryArrays>(c, out) {
+ Theory(c, out) {
}
void preRegisterTerm(TNode n) { Unimplemented(); }
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../../include -I@srcdir@/../..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libbooleans.la
libbooleans_la_SOURCES = \
- theory_def.h \
theory_bool.h
EXTRA_DIST = kinds
namespace theory {
namespace booleans {
-class TheoryBool : public TheoryImpl<TheoryBool> {
+class TheoryBool : public Theory {
public:
TheoryBool(context::Context* c, OutputChannel& out) :
- TheoryImpl<TheoryBool>(c, out) {
+ Theory(c, out) {
}
void preRegisterTerm(TNode n) { Unimplemented(); }
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../../include -I@srcdir@/../..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libbv.la
libbv_la_SOURCES = \
- theory_def.h \
theory_bv.h
EXTRA_DIST = kinds
namespace theory {
namespace bv {
-class TheoryBV : public TheoryImpl<TheoryBV> {
+class TheoryBV : public Theory {
public:
TheoryBV(context::Context* c, OutputChannel& out) :
- TheoryImpl<TheoryBV>(c, out) {
+ Theory(c, out) {
}
void preRegisterTerm(TNode n) { Unimplemented(); }
namespace CVC4 {
namespace theory {
+Node Theory::get() {
+ Assert( !d_facts.empty(),
+ "Theory::get() called with assertion queue empty!" );
+
+ Node fact = d_facts.front();
+ d_facts.pop_front();
+
+ Debug("theory") << "Theory::get() => " << fact
+ << "(" << d_facts.size() << " left)" << std::endl;
+
+ if(! fact.getAttribute(RegisteredAttr())) {
+ std::list<TNode> toReg;
+ toReg.push_back(fact);
+
+ Debug("theory") << "Theory::get(): registering new atom" << std::endl;
+
+ /* Essentially this is doing a breadth-first numbering of
+ * non-registered subterms with children. Any non-registered
+ * leaves are immediately registered. */
+ for(std::list<TNode>::iterator workp = toReg.begin();
+ workp != toReg.end();
+ ++workp) {
+
+ TNode n = *workp;
+
+ if(n.hasOperator()) {
+ TNode c = n.getOperator();
+
+ if(! c.getAttribute(RegisteredAttr())) {
+ if(c.getNumChildren() == 0) {
+ c.setAttribute(RegisteredAttr(), true);
+ registerTerm(c);
+ } else {
+ toReg.push_back(c);
+ }
+ }
+ }
+
+ for(TNode::iterator i = n.begin(); i != n.end(); ++i) {
+ TNode c = *i;
+
+ if(! c.getAttribute(RegisteredAttr())) {
+ if(c.getNumChildren() == 0) {
+ c.setAttribute(RegisteredAttr(), true);
+ registerTerm(c);
+ } else {
+ toReg.push_back(c);
+ }
+ }
+ }
+ }
+
+ /* Now register the list of terms in reverse order. Between this
+ * and the above registration of leaves, this should ensure that
+ * all subterms in the entire tree were registered in
+ * reverse-topological order. */
+ for(std::list<TNode>::reverse_iterator i = toReg.rbegin();
+ i != toReg.rend();
+ ++i) {
+
+ TNode n = *i;
+
+ /* Note that a shared TNode in the DAG rooted at "fact" could
+ * appear twice on the list, so we have to avoid hitting it
+ * twice. */
+ // FIXME when ExprSets are online, use one of those to avoid
+ // duplicates in the above?
+ if(! n.getAttribute(RegisteredAttr())) {
+ n.setAttribute(RegisteredAttr(), true);
+ registerTerm(n);
+ }
+ }
+ }
+
+ return fact;
+}
+
}/* CVC4::theory namespace */
}/* CVC4 namespace */
struct RewriteCacheTag {};
typedef expr::Attribute<RewriteCacheTag, TNode> RewriteCache;
-template <class T>
-class TheoryImpl;
-
/**
* Base class for T-solvers. Abstract DPLL(T).
*
* This is essentially an interface class. The TheoryEngine has
- * pointers to Theory. But each individual theory implementation T
- * should inherit from TheoryImpl<T>, which specializes a few things
- * for that theory.
+ * pointers to Theory. Note that only one specific Theory type (e.g.,
+ * TheoryUF) can exist per NodeManager, because of how the
+ * RegisteredAttr works. (If you need multiple instances of the same
+ * theory, you'll have to write a multiplexed theory that dispatches
+ * all calls to them.)
*/
class Theory {
private:
- template <class T>
- friend class ::CVC4::theory::TheoryImpl;
-
friend class ::CVC4::TheoryEngine;
- /**
- * Construct a Theory.
- */
- Theory(context::Context* ctxt, OutputChannel& out) throw() :
- d_context(ctxt),
- d_facts(),
- d_factsResetter(*this),
- d_out(&out) {
- }
-
/**
* Disallow default construction.
*/
protected:
+ /**
+ * Construct a Theory.
+ */
+ Theory(context::Context* ctxt, OutputChannel& out) throw() :
+ d_context(ctxt),
+ d_facts(),
+ d_factsResetter(*this),
+ d_out(&out) {
+ }
+
/**
* This is called at shutdown time by the TheoryEngine, just before
* destruction. It is important because there are destruction
* ordering issues between PropEngine and Theory (based on what
* hard-links to Nodes are outstanding). As the fact queue might be
* nonempty, we ensure here that it's clear. If you overload this,
- * you must make an explicit call here to the Theory implementation
- * of this function too.
+ * you must make an explicit call here to this->Theory::shutdown()
+ * too.
*/
virtual void shutdown() {
d_facts.clear();
return n.getAttribute(RewriteCache());
}
+ /** Tag for the "registerTerm()-has-been-called" flag on Nodes */
+ struct Registered {};
+ /** The "registerTerm()-has-been-called" flag on Nodes */
+ typedef CVC4::expr::CDAttribute<Registered, bool> RegisteredAttr;
+
+ /** Tag for the "preRegisterTerm()-has-been-called" flag on Nodes */
+ struct PreRegistered {};
+ /** The "preRegisterTerm()-has-been-called" flag on Nodes */
+ typedef CVC4::expr::Attribute<PreRegistered, bool> PreRegisteredAttr;
+
+ /**
+ * Returns the next atom in the assertFact() queue. Guarantees that
+ * registerTerm() has been called on the theory specific subterms.
+ *
+ * @return the next atom in the assertFact() queue.
+ */
+ Node get();
+
public:
/**
};/* class Theory */
-
-/**
- * Base class for T-solver implementations. Each individual
- * implementation T of the Theory interface should inherit from
- * TheoryImpl<T>. This class specializes some things for a particular
- * theory implementation.
- *
- * The problem with this is that Theory implementations cannot be
- * further subclassed without designing all non-children in the type
- * DAG to play the same trick as here (be template-polymorphic in their
- * most-derived child), linearizing the inheritance hierarchy (viewing
- * each instantiation separately).
- */
-template <class T>
-class TheoryImpl : public Theory {
-
-protected:
-
- /**
- * Construct a Theory.
- */
- TheoryImpl(context::Context* ctxt, OutputChannel& out) :
- Theory(ctxt, out) {
- /* FIXME: assert here that a TheoryImpl<T> doesn't already exist
- * for this NodeManager?? If it does, we're hosed because they'll
- * share per-theory node attributes. */
- }
-
- /** Tag for the "registerTerm()-has-been-called" flag on Nodes */
- struct Registered {};
- /** The "registerTerm()-has-been-called" flag on Nodes */
- typedef CVC4::expr::CDAttribute<Registered, bool> RegisteredAttr;
-
- /** Tag for the "preRegisterTerm()-has-been-called" flag on Nodes */
- struct PreRegistered {};
- /** The "preRegisterTerm()-has-been-called" flag on Nodes */
- typedef CVC4::expr::Attribute<PreRegistered, bool> PreRegisteredAttr;
-
- /**
- * Returns the next atom in the assertFact() queue. Guarantees that
- * registerTerm() has been called on the theory specific subterms.
- *
- * @return the next atom in the assertFact() queue.
- */
- Node get();
-};/* class TheoryImpl<T> */
-
-template <class T>
-Node TheoryImpl<T>::get() {
- Assert(typeid(*this) == typeid(T),
- "Improper Theory inheritance chain detected.");
-
- Assert( !d_facts.empty(),
- "Theory::get() called with assertion queue empty!" );
-
- Node fact = d_facts.front();
- d_facts.pop_front();
-
- Debug("theory") << "Theory::get() => " << fact << "(" << d_facts.size() << " left)" << std::endl;
-
- if(! fact.getAttribute(RegisteredAttr())) {
- std::list<TNode> toReg;
- toReg.push_back(fact);
-
- Debug("theory") << "Theory::get(): registering new atom" << std::endl;
-
- /* Essentially this is doing a breadth-first numbering of
- * non-registered subterms with children. Any non-registered
- * leaves are immediately registered. */
- for(std::list<TNode>::iterator workp = toReg.begin();
- workp != toReg.end();
- ++workp) {
-
- TNode n = *workp;
-
- if(n.hasOperator()) {
- TNode c = n.getOperator();
-
- if(! c.getAttribute(RegisteredAttr())) {
- if(c.getNumChildren() == 0) {
- c.setAttribute(RegisteredAttr(), true);
- registerTerm(c);
- } else {
- toReg.push_back(c);
- }
- }
- }
-
- for(TNode::iterator i = n.begin(); i != n.end(); ++i) {
- TNode c = *i;
-
- if(! c.getAttribute(RegisteredAttr())) {
- if(c.getNumChildren() == 0) {
- c.setAttribute(RegisteredAttr(), true);
- registerTerm(c);
- } else {
- toReg.push_back(c);
- }
- }
- }
- }
-
- /* Now register the list of terms in reverse order. Between this
- * and the above registration of leaves, this should ensure that
- * all subterms in the entire tree were registered in
- * reverse-topological order. */
- for(std::list<TNode>::reverse_iterator i = toReg.rbegin();
- i != toReg.rend();
- ++i) {
-
- TNode n = *i;
-
- /* Note that a shared TNode in the DAG rooted at "fact" could
- * appear twice on the list, so we have to avoid hitting it
- * twice. */
- // FIXME when ExprSets are online, use one of those to avoid
- // duplicates in the above?
- if(! n.getAttribute(RegisteredAttr())) {
- n.setAttribute(RegisteredAttr(), true);
- registerTerm(n);
- }
- }
- }
-
- return fact;
-}
-
}/* CVC4::theory namespace */
}/* CVC4 namespace */
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../../include -I@srcdir@/../..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libuf.la
libuf_la_SOURCES = \
- theory_def.h \
ecdata.h \
ecdata.cpp \
theory_uf.h \
** See the file COPYING in the top-level source directory for licensing
** information.
**
- **
+ ** Implementation of the theory of uninterpreted functions.
**/
-
#include "theory/uf/theory_uf.h"
#include "theory/uf/ecdata.h"
#include "expr/kind.h"
using namespace CVC4::theory;
using namespace CVC4::theory::uf;
-
-
TheoryUF::TheoryUF(Context* c, OutputChannel& out) :
- TheoryImpl<TheoryUF>(c, out),
+ Theory(c, out),
d_assertions(c),
d_pending(c),
d_currentPendingIdx(c,0),
d_disequality(c),
- d_registered(c)
-{}
+ d_registered(c) {
+}
-TheoryUF::~TheoryUF(){}
+TheoryUF::~TheoryUF() {
+}
-void TheoryUF::preRegisterTerm(TNode n){
+void TheoryUF::preRegisterTerm(TNode n) {
Debug("uf") << "uf: begin preRegisterTerm(" << n << ")" << std::endl;
Debug("uf") << "uf: end preRegisterTerm(" << n << ")" << std::endl;
}
-void TheoryUF::registerTerm(TNode n){
+void TheoryUF::registerTerm(TNode n) {
Debug("uf") << "uf: begin registerTerm(" << n << ")" << std::endl;
-
d_registered.push_back(n);
-
-
-
ECData* ecN;
- if(n.getAttribute(ECAttr(), ecN)){
+ if(n.getAttribute(ECAttr(), ecN)) {
/* registerTerm(n) is only called when a node has not been seen in the
* current context. ECAttr() is not a context-dependent attribute.
* When n.hasAttribute(ECAttr(),...) is true on a registerTerm(n) call,
"Expected getWatchListSize() == 0. "
"This data is either already in use or was not properly maintained "
"during backtracking");
- }else{
+ } else {
//The attribute does not exist, so it is created and set
ecN = new (true) ECData(getContext(), n);
n.setAttribute(ECAttr(), ecN);
/* If the node is an APPLY_UF, we need to add it to the predecessor list
* of its children.
*/
- if(n.getKind() == APPLY_UF){
+ if(n.getKind() == APPLY_UF) {
TNode::iterator cIter = n.begin();
- for(; cIter != n.end(); ++cIter){
+ for(; cIter != n.end(); ++cIter) {
TNode child = *cIter;
/* Because this can be called after nodes have been merged, we need
/* Because this can be called after nodes have been merged we may need
* to be merged with other predecessors of the equivalence class.
*/
- for(Link* Px = ecChild->getFirst(); Px != NULL; Px = Px->d_next ){
- if(equiv(n, Px->d_data)){
+ for(Link* Px = ecChild->getFirst(); Px != NULL; Px = Px->d_next ) {
+ if(equiv(n, Px->d_data)) {
Node pend = n.eqNode(Px->d_data);
d_pending.push_back(pend);
}
}
-bool TheoryUF::sameCongruenceClass(TNode x, TNode y){
+bool TheoryUF::sameCongruenceClass(TNode x, TNode y) {
return
ccFind(x.getAttribute(ECAttr())) ==
ccFind(y.getAttribute(ECAttr()));
}
-bool TheoryUF::equiv(TNode x, TNode y){
+bool TheoryUF::equiv(TNode x, TNode y) {
Assert(x.getKind() == kind::APPLY_UF);
Assert(y.getKind() == kind::APPLY_UF);
- if(x.getNumChildren() != y.getNumChildren())
+ if(x.getNumChildren() != y.getNumChildren()) {
return false;
+ }
- if(x.getOperator() != y.getOperator())
+ if(x.getOperator() != y.getOperator()) {
return false;
+ }
// intentionally don't look at operator
TNode::iterator xIter = x.begin();
TNode::iterator yIter = y.begin();
- while(xIter != x.end()){
+ while(xIter != x.end()) {
- if(!sameCongruenceClass(*xIter, *yIter)){
+ if(!sameCongruenceClass(*xIter, *yIter)) {
return false;
}
* many better algorithms use eager path compression.
* 2) Elminate recursion.
*/
-ECData* TheoryUF::ccFind(ECData * x){
- if( x->getFind() == x)
+ECData* TheoryUF::ccFind(ECData * x) {
+ if(x->getFind() == x) {
return x;
- else{
+ } else {
return ccFind(x->getFind());
}
/* Slightly better Find w/ path compression and no recursion*/
ECData* start;
ECData* next = x;
while(x != x->getFind()) x=x->getRep();
- while( (start = next) != x){
+ while( (start = next) != x) {
next = start->getFind();
start->setFind(x);
}
*/
}
-void TheoryUF::ccUnion(ECData* ecX, ECData* ecY){
+void TheoryUF::ccUnion(ECData* ecX, ECData* ecY) {
ECData* nslave;
ECData* nmaster;
- if(ecX->getWatchListSize() <= ecY->getWatchListSize()){
+ if(ecX->getWatchListSize() <= ecY->getWatchListSize()) {
nslave = ecX;
nmaster = ecY;
- }else{
+ } else {
nslave = ecY;
nmaster = ecX;
}
nslave->setFind(nmaster);
- for(Link* Px = nmaster->getFirst(); Px != NULL; Px = Px->d_next ){
- for(Link* Py = nslave->getFirst(); Py != NULL; Py = Py->d_next ){
- if(equiv(Px->d_data,Py->d_data)){
+ for(Link* Px = nmaster->getFirst(); Px != NULL; Px = Px->d_next ) {
+ for(Link* Py = nslave->getFirst(); Py != NULL; Py = Py->d_next ) {
+ if(equiv(Px->d_data,Py->d_data)) {
Node pendingEq = (Px->d_data).eqNode(Py->d_data);
d_pending.push_back(pendingEq);
}
ECData::takeOverDescendantWatchList(nslave, nmaster);
}
-void TheoryUF::merge(){
+void TheoryUF::merge() {
while(d_currentPendingIdx < d_pending.size() ) {
Node assertion = d_pending[d_currentPendingIdx];
d_currentPendingIdx = d_currentPendingIdx + 1;
}
}
-Node TheoryUF::constructConflict(TNode diseq){
+Node TheoryUF::constructConflict(TNode diseq) {
Debug("uf") << "uf: begin constructConflict()" << std::endl;
NodeBuilder<> nb(kind::AND);
return conflict;
}
-void TheoryUF::check(Effort level){
+void TheoryUF::check(Effort level) {
Debug("uf") << "uf: begin check(" << level << ")" << std::endl;
- while(!done()){
+ while(!done()) {
Node assertion = get();
Debug("uf") << "TheoryUF::check(): " << assertion << std::endl;
- switch(assertion.getKind()){
+ switch(assertion.getKind()) {
case EQUAL:
d_assertions.push_back(assertion);
d_pending.push_back(assertion);
}
//Make sure all outstanding merges are completed.
- if(d_currentPendingIdx < d_pending.size()){
+ if(d_currentPendingIdx < d_pending.size()) {
merge();
}
- if(fullEffort(level)){
+ if(fullEffort(level)) {
for(CDList<Node>::const_iterator diseqIter = d_disequality.begin();
diseqIter != d_disequality.end();
- ++diseqIter){
+ ++diseqIter) {
TNode left = (*diseqIter)[0];
TNode right = (*diseqIter)[1];
- if(sameCongruenceClass(left, right)){
+ if(sameCongruenceClass(left, right)) {
Node remakeNeq = (*diseqIter).notNode();
Node conflict = constructConflict(remakeNeq);
d_out->conflict(conflict, false);
}
Debug("uf") << "uf: end check(" << level << ")" << std::endl;
-
}
namespace theory {
namespace uf {
-class TheoryUF : public TheoryImpl<TheoryUF> {
+class TheoryUF : public Theory {
private:
/** Constructs a conflict from an inconsistent disequality. */
Node constructConflict(TNode diseq);
-};
+};/* class TheoryUF */
/**
* Cleanup function for ECData. This will be used for called whenever
* a ECAttr is being destructed.
*/
-struct ECCleanupStrategy{
- static void cleanup(ECData* ec){
+struct ECCleanupStrategy {
+ static void cleanup(ECData* ec) {
Debug("ufgc") << "cleaning up ECData " << ec << "\n";
ec->deleteSelf();
}
-};
+};/* struct ECCleanupStrategy */
/** Unique name to use for constructing ECAttr. */
-struct EquivClass;
+struct ECAttrTag {};
/**
* ECAttr is the attribute that maps a node to an equivalence class.
*/
-typedef expr::Attribute<EquivClass, ECData*, ECCleanupStrategy > ECAttr;
-
-} /* CVC4::theory::uf namespace */
-} /* CVC4::theory namespace */
-} /* CVC4 namespace */
+typedef expr::Attribute<ECAttrTag, ECData*, ECCleanupStrategy> ECAttr;
+}/* CVC4::theory::uf namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
#endif /* __CVC4__THEORY__UF__THEORY_UF_H */
setMessage(string(buf));
#ifdef CVC4_DEBUG
- // we leak buf[] but only in debug mode with assertions failing
- s_debugAssertionFailure = buf;
+ if(s_debugAssertionFailure == NULL) {
+ // we leak buf[] but only in debug mode with assertions failing
+ s_debugAssertionFailure = buf;
+ }
#else /* CVC4_DEBUG */
delete [] buf;
#endif /* CVC4_DEBUG */
#ifdef CVC4_DEBUG
// we leak buf[] but only in debug mode with assertions failing
- s_debugAssertionFailure = buf;
+ if(s_debugAssertionFailure == NULL) {
+ s_debugAssertionFailure = buf;
+ }
#else /* CVC4_DEBUG */
delete [] buf;
#endif /* CVC4_DEBUG */
AM_CPPFLAGS = \
-D__BUILDING_CVC4LIB \
-I@srcdir@/../include -I@srcdir@/..
-AM_CXXFLAGS = -Wall -fvisibility=hidden
+AM_CXXFLAGS = -Wall $(FLAG_VISIBILITY_HIDDEN)
noinst_LTLIBRARIES = libutil.la
This is a pre-release of CVC4.\n\
Copyright (C) 2009, 2010\n\
The ACSys Group\n\
- Courant Institute of Mathematical Sciences,\n\
+ Courant Institute of Mathematical Sciences\n\
New York University\n\
New York, NY 10012 USA\n");
}
SUBDIRS = precedence uf
-TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/../../bin/cvc4
+TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/src/main/cvc4
TESTS = \
+ error.cvc \
+ boolean-prec.cvc \
distinct.smt \
flet.smt \
flet2.smt \
wiki.19.cvc \
wiki.20.cvc \
wiki.21.cvc
-
+
# synonyms for "check"
.PHONY: regress regress0 test
regress regress0 test: check
-% Expect: VALID
+% EXPECT: VALID
% Simple test for right precedence of AND, <=>, NOT.
A, B, C: BOOLEAN;
QUERY (NOT A AND NOT B <=> C) <=> (((NOT A) AND (NOT B)) <=> C);
+% EXIT: 20
ELSE FALSE
ENDIF;
QUERY a288;
+% EXIT: 20
ASSERT (x = 3);
ASSERT (y = 2);
QUERY(f(x) > f (y));
+% EXIT: 20
ASSERT(a);
QUERY(a OR b);
+% EXIT: 20
--- /dev/null
+% EXPECT-ERROR: CVC4 Error:
+% EXPECT-ERROR: Parse Error: Parser Error: error.cvc:3.9: Symbol BOOL not declared
+p : BOOL;
+% EXIT: 1
a, b, c: BOOLEAN;
% EXPECT: VALID
QUERY (a XOR b) <=> (NOT a AND b) OR (NOT b AND a);
+% EXIT: 20
a, b, c: BOOLEAN;
% EXPECT: INVALID
QUERY NOT c AND b;
+% EXIT: 10
a, b, c: BOOLEAN;
% EXPECT: VALID
QUERY (IF c THEN a ELSE b ENDIF) <=> ((c AND a) OR (NOT c AND b));
+% EXIT: 20
a, b, c: BOOLEAN;
% EXPECT: VALID
QUERY (a => b) <=> (NOT a OR b);
+% EXIT: 20
% EXPECT: VALID
QUERY TRUE XOR FALSE;
+% EXIT: 20
-TESTS_ENVIRONMENT = @srcdir@/../../run_regression @top_builddir@/../../bin/cvc4
+TESTS_ENVIRONMENT = @srcdir@/../../run_regression @top_builddir@/src/main/cvc4
TESTS = \
iff-implies.cvc \
implies-iff.cvc \
A, B: BOOLEAN;
QUERY (A AND NOT B) <=> (A AND (NOT B));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A AND B XOR C) <=> ((A AND B) XOR C);
+% EXIT: 20
f : T -> T;
QUERY (f(x) = f(y)) <=> ((f(x)) = (f(y)));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A <=> B <=> C) <=> (A <=> (B <=> C));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A <=> B => C) <=> ((A <=> (B => C)));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A => B => C) <=> (A => (B => C));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A => B <=> C) <=> ((A => B) <=> C);
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A => B OR C) <=> (A => (B OR C));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (NOT A AND B) <=> ((NOT A) AND B);
+% EXIT: 20
A, B: BOOLEAN;
QUERY (NOT A = B) <=> (NOT (A = B));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A OR B => C) <=> ((A OR B) => C);
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A OR B XOR C) <=> (A OR (B XOR C));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A XOR B AND C) <=> (A XOR (B AND C));
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A XOR B XOR C) <=> ((A XOR B) XOR C);
+% EXIT: 20
A, B, C: BOOLEAN;
QUERY (A XOR B OR C) <=> ((A XOR B) OR C);
+% EXIT: 20
% EXPECT: INVALID
QUERY (a OR b);
+% EXIT: 10
ASSERT x1 AND NOT x1;
% EXPECT: VALID
QUERY x2;
+% EXIT: 20
% EXPECT: INVALID
QUERY FALSE;
+% EXIT: 10
% EXPECT: VALID
QUERY FALSE;
+% EXIT: 20
POP;
PUSH;
QUERY FALSE;
+% EXIT: 20
P,Q:BOOLEAN;
ASSERT (P OR Q);
QUERY (P OR Q);
+% EXIT: 20
-TESTS_ENVIRONMENT = @srcdir@/../../run_regression @top_builddir@/../../bin/cvc4
+TESTS_ENVIRONMENT = @srcdir@/../../run_regression @top_builddir@/src/main/cvc4
TESTS = \
euf_simp01.smt \
euf_simp02.smt \
f: A -> B;
QUERY (x = y => f(x) = f(y));
+% EXIT: 20
f: A -> B;
QUERY (f(x) = f(y));
+% EXIT: 10
ASSERT (x = a AND y = a) OR (x = b AND y = b);
QUERY (f(x) = f(y));
+% EXIT: 20
ASSERT (x = a OR x = b) AND (y = b OR y = a);
QUERY (f(x) = f(y));
+% EXIT: 10
% EXPECT: VALID
QUERY a OR (b OR c) <=> (a OR b) OR c;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND (b AND c) <=> (a AND b) AND c;
+% EXIT: 20
% EXPECT: VALID
QUERY a OR b <=> b OR a;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND b <=> b AND a;
+% EXIT: 20
% EXPECT: VALID
QUERY a OR (a AND b) <=> a;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND (a OR b) <=> a;
+% EXIT: 20
% EXPECT: VALID
QUERY a OR (b AND c) <=> (a OR b) AND (a OR c);
+% EXIT: 20
% EXPECT: VALID
QUERY a AND (b OR c) <=> (a AND b) OR (a AND c);
+% EXIT: 20
% EXPECT: VALID
QUERY a OR NOT a;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND NOT a <=> FALSE;
+% EXIT: 20
% EXPECT: VALID
QUERY a OR a <=> a;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND a <=> a;
+% EXIT: 20
% EXPECT: VALID
QUERY a OR FALSE <=> a;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND TRUE <=> a;
+% EXIT: 20
% EXPECT: VALID
QUERY a OR TRUE <=> TRUE;
+% EXIT: 20
% EXPECT: VALID
QUERY a AND FALSE <=> FALSE;
+% EXIT: 20
% EXPECT: VALID
QUERY NOT FALSE <=> TRUE;
+% EXIT: 20
% EXPECT: VALID
QUERY NOT TRUE <=> FALSE;
+% EXIT: 20
% EXPECT: VALID
QUERY NOT (a OR b) <=> NOT a AND NOT b;
+% EXIT: 20
% EXPECT: VALID
QUERY NOT (a AND b) <=> NOT a OR NOT b;
+% EXIT: 20
% EXPECT: VALID
QUERY NOT NOT a <=> a;
+% EXIT: 20
-TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/../../bin/cvc4
+TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/src/main/cvc4
TESTS = friedman_n4_i5.smt \
hole7.cvc \
hole8.cvc \
-TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/../../bin/cvc4
+TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/src/main/cvc4
TESTS = bmc-galileo-8.smt \
bmc-galileo-9.smt \
bmc-ibm-10.smt \
-TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/../../bin/cvc4
+TESTS_ENVIRONMENT = @srcdir@/../run_regression @top_builddir@/src/main/cvc4
TESTS = C880mul.miter.shuffled-as.sat03-348.smt \
comb2.shuffled-as.sat03-420.smt \
hole10.cvc \
fi
elif expr "$benchmark" : '.*\.cvc$' &>/dev/null; then
expected_output=`grep '^% EXPECT: ' "$benchmark" | sed 's,^% EXPECT: ,,'`
- if [ -z "$expected_output" ]; then
- error "cannot determine status of \`$benchmark'"
+ expected_error=`grep '^% EXPECT-ERROR: ' "$benchmark" | sed 's,^% EXPECT-ERROR: ,,'`
+ if [ -z "$expected_output" -a -z "$expected_error" ]; then
+ error "cannot determine expected output of \`$benchmark': " \
+ "please use \`% EXPECT:' and/or \`% EXPECT-ERROR:' gestures"
fi
expected_exit_status=`grep -m 1 '^% EXIT: ' "$benchmark" | sed 's,^% EXIT: ,,'`
+ if [ -z "$expected_exit_status" ]; then
+ error "cannot determine expected exit status of \`$benchmark': please use \`% EXIT:' gesture"
+ fi
else
error "benchmark \`$benchmark' must be *.cvc or *.smt"
fi
-expfile=`mktemp -t cvc4_expected.XXXXXXXXXX`
-outfile=`mktemp -t cvc4_output.XXXXXXXXXX`
-echo "$expected_output" >"$expfile"
+expoutfile=`mktemp -t cvc4_expect_stdout.XXXXXXXXXX`
+experrfile=`mktemp -t cvc4_expect_stderr.XXXXXXXXXX`
+outfile=`mktemp -t cvc4_stdout.XXXXXXXXXX`
+errfile=`mktemp -t cvc4_stderr.XXXXXXXXXX`
+exitstatusfile=`mktemp -t cvc4_exitstatus.XXXXXXXXXX`
+if [ -z "$expected_output" ]; then
+ # in case expected stdout output is empty, make sure we don't differ
+ # by a newline, which we would if we echo "" >"$expoutfile"
+ touch "$expoutfile"
+else
+ echo "$expected_output" >"$expoutfile"
+fi
+if [ -z "$expected_error" ]; then
+ # in case expected stderr output is empty, make sure we don't differ
+ # by a newline, which we would if we echo "" >"$experrfile"
+ touch "$experrfile"
+else
+ echo "$expected_error" >"$experrfile"
+fi
-# echo "$cvc4" --segv-nospin "$benchmark"
-"$cvc4" --segv-nospin "$benchmark" > "$outfile"
+("$cvc4" --segv-nospin "$benchmark"; echo $? >"$exitstatusfile") > "$outfile" 2> "$errfile"
-diffs=`diff -u "$expfile" "$outfile"`
+diffs=`diff -u "$expoutfile" "$outfile"`
diffexit=$?
-rm -f "$expfile"
+diffserr=`diff -u "$experrfile" "$errfile"`
+diffexiterr=$?
+exit_status=`cat "$exitstatusfile"`
+
+rm -f "$expoutfile"
+rm -f "$experrfile"
rm -f "$outfile"
+rm -f "$errfile"
+rm -f "$exitstatusfile"
+
+exitcode=0
if [ $diffexit -ne 0 ]; then
- echo "$prog: error: differences between expected and actual output"
+ echo "$prog: error: differences between expected and actual output on stdout"
echo "$diffs"
- exit 1
+ exitcode=1
+fi
+if [ $diffexiterr -ne 0 ]; then
+ echo "$prog: error: differences between expected and actual output on stderr"
+ echo "$diffserr"
+ exitcode=1
fi
-if [ -n "$expected_exit_status" ]; then
- :
- #if [ $exit_status != "$expected_exit_status" ]; then
- # error "expected exit status \`$expected_exit_status' but got \`$exit_status'"
- #fi
+if [ "$exit_status" != "$expected_exit_status" ]; then
+ echo "$prog: error: expected exit status \`$expected_exit_status' but got \`$exit_status'"
+ exitcode=1
fi
+exit $exitcode
expr/attribute_black \
parser/parser_white \
context/context_black \
+ context/context_white \
context/context_mm_black \
context/cdo_black \
context/cdlist_black \
void setUp() {
d_context = new Context;
//Debug.on("cdmap");
+ //Debug.on("gc");
+ //Debug.on("pushpop");
}
void tearDown() {
--- /dev/null
+/********************* */
+/** context_white.h
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009, 2010 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.
+ **
+ ** White box testing of CVC4::context::Context.
+ **/
+
+#include <cxxtest/TestSuite.h>
+
+#include "context/context.h"
+#include "context/cdo.h"
+#include "util/Assert.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::context;
+
+class ContextWhite : public CxxTest::TestSuite {
+private:
+
+ Context* d_context;
+
+public:
+
+ void setUp() {
+ d_context = new Context;
+ }
+
+ void tearDown() {
+ delete d_context;
+ }
+
+ void testContextSimple() {
+ Scope *s = d_context->getTopScope();
+
+ TS_ASSERT(s == d_context->getBottomScope());
+ TS_ASSERT(d_context->getLevel() == 0);
+ TS_ASSERT(d_context->d_scopeList.size() == 1);
+
+ TS_ASSERT(s->d_pContext == d_context);
+ TS_ASSERT(s->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(s->d_level == 0);
+ TS_ASSERT(s->d_pContextObjList == NULL);
+
+ CDO<int> a(d_context);
+
+ TS_ASSERT(s->d_pContext == d_context);
+ TS_ASSERT(s->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(s->d_level == 0);
+ TS_ASSERT(s->d_pContextObjList == &a);
+
+ TS_ASSERT(a.d_pScope == s);
+ TS_ASSERT(a.d_pContextObjRestore == NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &s->d_pContextObjList);
+
+ CDO<int> b(d_context);
+
+ TS_ASSERT(s->d_pContext == d_context);
+ TS_ASSERT(s->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(s->d_level == 0);
+ TS_ASSERT(s->d_pContextObjList == &b);
+
+ TS_ASSERT(a.d_pScope == s);
+ TS_ASSERT(a.d_pContextObjRestore == NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &b.d_pContextObjNext);
+
+ TS_ASSERT(b.d_pScope == s);
+ TS_ASSERT(b.d_pContextObjRestore == NULL);
+ TS_ASSERT(b.d_pContextObjNext == &a);
+ TS_ASSERT(b.d_ppContextObjPrev == &s->d_pContextObjList);
+
+ d_context->push();
+ Scope* t = d_context->getTopScope();
+ TS_ASSERT(s != t);
+
+ TS_ASSERT(s == d_context->getBottomScope());
+ TS_ASSERT(d_context->getLevel() == 1);
+ TS_ASSERT(d_context->d_scopeList.size() == 2);
+
+ TS_ASSERT(s->d_pContext == d_context);
+ TS_ASSERT(s->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(s->d_level == 0);
+ TS_ASSERT(s->d_pContextObjList == &b);
+
+ TS_ASSERT(t->d_pContext == d_context);
+ TS_ASSERT(t->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(t->d_level == 1);
+ TS_ASSERT(t->d_pContextObjList == NULL);
+
+ TS_ASSERT(a.d_pScope == s);
+ TS_ASSERT(a.d_pContextObjRestore == NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &b.d_pContextObjNext);
+
+ TS_ASSERT(b.d_pScope == s);
+ TS_ASSERT(b.d_pContextObjRestore == NULL);
+ TS_ASSERT(b.d_pContextObjNext == &a);
+ TS_ASSERT(b.d_ppContextObjPrev == &s->d_pContextObjList);
+
+ a = 5;
+
+ TS_ASSERT(t->d_pContext == d_context);
+ TS_ASSERT(t->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(t->d_level == 1);
+ TS_ASSERT(t->d_pContextObjList == &a);
+
+ TS_ASSERT(a.d_pScope == t);
+ TS_ASSERT(a.d_pContextObjRestore != NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &t->d_pContextObjList);
+
+ b = 3;
+
+ TS_ASSERT(t->d_pContext == d_context);
+ TS_ASSERT(t->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(t->d_level == 1);
+ TS_ASSERT(t->d_pContextObjList == &b);
+
+ TS_ASSERT(a.d_pScope == t);
+ TS_ASSERT(a.d_pContextObjRestore != NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &b.d_pContextObjNext);
+
+ TS_ASSERT(b.d_pScope == t);
+ TS_ASSERT(b.d_pContextObjRestore != NULL);
+ TS_ASSERT(b.d_pContextObjNext == &a);
+ TS_ASSERT(b.d_ppContextObjPrev == &t->d_pContextObjList);
+
+ d_context->push();
+ Scope* u = d_context->getTopScope();
+ TS_ASSERT(u != t);
+ TS_ASSERT(u != s);
+
+ CDO<int> c(d_context);
+ c = 4;
+
+ TS_ASSERT(c.d_pScope == u);
+ TS_ASSERT(c.d_pContextObjRestore != NULL);
+ TS_ASSERT(c.d_pContextObjNext == NULL);
+ TS_ASSERT(c.d_ppContextObjPrev == &u->d_pContextObjList);
+
+ d_context->pop();
+
+ TS_ASSERT(t->d_pContext == d_context);
+ TS_ASSERT(t->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(t->d_level == 1);
+ TS_ASSERT(t->d_pContextObjList == &b);
+
+ TS_ASSERT(a.d_pScope == t);
+ TS_ASSERT(a.d_pContextObjRestore != NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &b.d_pContextObjNext);
+
+ TS_ASSERT(b.d_pScope == t);
+ TS_ASSERT(b.d_pContextObjRestore != NULL);
+ TS_ASSERT(b.d_pContextObjNext == &a);
+ //TS_ASSERT(b.d_ppContextObjPrev == &t->d_pContextObjList);// THIS ONE FAILS
+
+ d_context->pop();
+
+ TS_ASSERT(s->d_pContext == d_context);
+ TS_ASSERT(s->d_pCMM == d_context->d_pCMM);
+ TS_ASSERT(s->d_level == 0);
+ //TS_ASSERT(s->d_pContextObjList == &b);// THIS ONE FAILS
+
+ TS_ASSERT(a.d_pScope == s);
+ TS_ASSERT(a.d_pContextObjRestore == NULL);
+ TS_ASSERT(a.d_pContextObjNext == NULL);
+ TS_ASSERT(a.d_ppContextObjPrev == &b.d_pContextObjNext);
+
+ TS_ASSERT(b.d_pScope == s);
+ TS_ASSERT(b.d_pContextObjRestore == NULL);
+ TS_ASSERT(b.d_pContextObjNext == &a);
+ TS_ASSERT(b.d_ppContextObjPrev == &s->d_pContextObjList);
+ }
+};
#include <string>
+#include "context/context.h"
#include "expr/node_value.h"
#include "expr/node_builder.h"
#include "expr/node_manager.h"
-#include "expr/node.h"
#include "expr/attribute.h"
-#include "context/context.h"
+#include "expr/node.h"
+#include "theory/theory.h"
+#include "theory/uf/theory_uf.h"
#include "util/Assert.h"
using namespace CVC4;
}
void testAttributeIds() {
- TS_ASSERT(VarNameAttr::s_id == 0);
- TS_ASSERT(TestStringAttr1::s_id == 1);
- TS_ASSERT(TestStringAttr2::s_id == 2);
- TS_ASSERT((attr::LastAttributeId<string, false>::s_id == 3));
-
- TS_ASSERT(TypeAttr::s_id == 0);
- TS_ASSERT((attr::LastAttributeId<void*, false>::s_id == 1));
-
- TS_ASSERT(TestFlag1::s_id == 0);
- TS_ASSERT(TestFlag2::s_id == 1);
- TS_ASSERT(TestFlag3::s_id == 2);
- TS_ASSERT(TestFlag4::s_id == 3);
- TS_ASSERT(TestFlag5::s_id == 4);
- TS_ASSERT((attr::LastAttributeId<bool, false>::s_id == 5));
-
- TS_ASSERT(TestFlag1cd::s_id == 0);
- TS_ASSERT(TestFlag2cd::s_id == 1);
- TS_ASSERT((attr::LastAttributeId<bool, true>::s_id == 2));
+ // Test that IDs for (a subset of) attributes in the system are
+ // unique and that the LastAttributeId (which would be the next ID
+ // to assign) is greater than all attribute IDs.
+
+ // We used to check ID assignments explicitly. However, between
+ // compilation modules, you don't get a strong guarantee
+ // (initialization order is somewhat implementation-specific, and
+ // anyway you'd have to change the tests anytime you add an
+ // attribute). So we back off, and just test that they're unique
+ // and that the next ID to be assigned is strictly greater than
+ // those that have already been assigned.
+
+ unsigned lastId = attr::LastAttributeId<string, false>::s_id;
+ TS_ASSERT_LESS_THAN(VarNameAttr::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestStringAttr1::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestStringAttr2::s_id, lastId);
+
+ TS_ASSERT_DIFFERS(VarNameAttr::s_id, TestStringAttr1::s_id);
+ TS_ASSERT_DIFFERS(VarNameAttr::s_id, TestStringAttr2::s_id);
+ TS_ASSERT_DIFFERS(TestStringAttr1::s_id, TestStringAttr2::s_id);
+
+ lastId = attr::LastAttributeId<void*, false>::s_id;
+ TS_ASSERT_LESS_THAN(NodeManager::TypeAttr::s_id, lastId);
+ TS_ASSERT_LESS_THAN(theory::uf::ECAttr::s_id, lastId);
+ TS_ASSERT_DIFFERS(NodeManager::TypeAttr::s_id, theory::uf::ECAttr::s_id);
+
+ lastId = attr::LastAttributeId<bool, false>::s_id;
+ TS_ASSERT_LESS_THAN(NodeManager::AtomicAttr::s_id, lastId);
+ TS_ASSERT_LESS_THAN(theory::Theory::PreRegisteredAttr::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag1::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag2::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag3::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag4::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag5::s_id, lastId);
+ TS_ASSERT_DIFFERS(NodeManager::AtomicAttr::s_id,
+ theory::Theory::PreRegisteredAttr::s_id);
+ TS_ASSERT_DIFFERS(NodeManager::AtomicAttr::s_id, TestFlag1::s_id);
+ TS_ASSERT_DIFFERS(NodeManager::AtomicAttr::s_id, TestFlag2::s_id);
+ TS_ASSERT_DIFFERS(NodeManager::AtomicAttr::s_id, TestFlag3::s_id);
+ TS_ASSERT_DIFFERS(NodeManager::AtomicAttr::s_id, TestFlag4::s_id);
+ TS_ASSERT_DIFFERS(NodeManager::AtomicAttr::s_id, TestFlag5::s_id);
+ TS_ASSERT_DIFFERS(theory::Theory::PreRegisteredAttr::s_id, TestFlag1::s_id);
+ TS_ASSERT_DIFFERS(theory::Theory::PreRegisteredAttr::s_id, TestFlag2::s_id);
+ TS_ASSERT_DIFFERS(theory::Theory::PreRegisteredAttr::s_id, TestFlag3::s_id);
+ TS_ASSERT_DIFFERS(theory::Theory::PreRegisteredAttr::s_id, TestFlag4::s_id);
+ TS_ASSERT_DIFFERS(theory::Theory::PreRegisteredAttr::s_id, TestFlag5::s_id);
+ TS_ASSERT_DIFFERS(TestFlag1::s_id, TestFlag2::s_id);
+ TS_ASSERT_DIFFERS(TestFlag1::s_id, TestFlag3::s_id);
+ TS_ASSERT_DIFFERS(TestFlag1::s_id, TestFlag4::s_id);
+ TS_ASSERT_DIFFERS(TestFlag1::s_id, TestFlag5::s_id);
+ TS_ASSERT_DIFFERS(TestFlag2::s_id, TestFlag3::s_id);
+ TS_ASSERT_DIFFERS(TestFlag2::s_id, TestFlag4::s_id);
+ TS_ASSERT_DIFFERS(TestFlag2::s_id, TestFlag5::s_id);
+ TS_ASSERT_DIFFERS(TestFlag3::s_id, TestFlag4::s_id);
+ TS_ASSERT_DIFFERS(TestFlag3::s_id, TestFlag5::s_id);
+ TS_ASSERT_DIFFERS(TestFlag4::s_id, TestFlag5::s_id);
+
+ lastId = attr::LastAttributeId<bool, true>::s_id;
+ TS_ASSERT_LESS_THAN(theory::Theory::RegisteredAttr::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag1cd::s_id, lastId);
+ TS_ASSERT_LESS_THAN(TestFlag2cd::s_id, lastId);
+ TS_ASSERT_DIFFERS(theory::Theory::RegisteredAttr::s_id, TestFlag1cd::s_id);
+ TS_ASSERT_DIFFERS(theory::Theory::RegisteredAttr::s_id, TestFlag2cd::s_id);
+ TS_ASSERT_DIFFERS(TestFlag1cd::s_id, TestFlag2cd::s_id);
+
+ lastId = attr::LastAttributeId<TNode, false>::s_id;
+ TS_ASSERT_LESS_THAN(theory::RewriteCache::s_id, lastId);
}
void testCDAttributes() {
TS_ASSERT(mult->isAtomic());
TS_ASSERT(plus->isAtomic());
TS_ASSERT(d->isAtomic());
- TS_ASSERT(!null->isAtomic());
+#ifdef CVC4_ASSERTIONS
+ TS_ASSERT_THROWS(null->isAtomic(), IllegalArgumentException);
+#endif /* CVC4_ASSERTIONS */
TS_ASSERT(i1->isAtomic());
TS_ASSERT(i2->isAtomic());
TS_ASSERT(!x.isAtomic());
TS_ASSERT(!y.isAtomic());
TS_ASSERT(!z.isAtomic());
+
+ Expr w1 = d_em->mkExpr(PLUS, d_em->mkExpr(ITE, z, *i1, *i2), *i2);
+ Expr w2 = d_em->mkExpr(PLUS, d_em->mkExpr(MULT, *i1, *i2), *i2);
+
+ TS_ASSERT(!w1.isAtomic());
+ TS_ASSERT(w2.isAtomic());
}
void testGetConst() {
Node n = noKind;
-#ifdef CVC4_DEBUG
- TS_ASSERT_THROWS_ANYTHING(noKind.getKind(););
-#endif
+#ifdef CVC4_ASSERTIONS
+ TS_ASSERT_THROWS(noKind.getKind(), AssertionException);
+#endif /* CVC4_ASSERTIONS */
NodeBuilder<> spec(specKind);
TS_ASSERT_EQUALS(spec.getKind(), specKind);
push_back(noKind, K);
TS_ASSERT_EQUALS(noKind.getNumChildren(), K+K);
-#ifdef CVC4_DEBUG
+#ifdef CVC4_ASSERTIONS
noKind << specKind;
n = noKind;
- TS_ASSERT_THROWS_ANYTHING( noKind.getNumChildren() );
-#endif
+ TS_ASSERT_THROWS( noKind.getNumChildren(), AssertionException );
+#endif /* CVC4_ASSERTIONS */
}
void testOperatorSquare() {
Node i_2 = d_nm->mkConst(true);
Node i_K = d_nm->mkNode(NOT, i_0);
-#ifdef CVC4_DEBUG
- TS_ASSERT_THROWS_ANYTHING(arr[-1];);
- TS_ASSERT_THROWS_ANYTHING(arr[0];);
-#endif
+#ifdef CVC4_ASSERTIONS
+ TS_ASSERT_THROWS(arr[-1], AssertionException);
+ TS_ASSERT_THROWS(arr[0], AssertionException);
+#endif /* CVC4_ASSERTIONS */
arr << i_0;
}
TS_ASSERT_EQUALS(arr[K], i_K);
-#ifdef CVC4_DEBUG
+#ifdef CVC4_ASSERTIONS
Node n = arr;
- TS_ASSERT_THROWS_ANYTHING(arr[0]);
-#endif
+ TS_ASSERT_THROWS(arr[0], AssertionException);
+#endif /* CVC4_ASSERTIONS */
}
void testClear() {
Node p = d_nm->mkNode(PLUS, z, d_nm->mkNode(UMINUS, x), z);
Node q = d_nm->mkNode(AND, x, z, d_nm->mkNode(NOT, y));
+#ifdef CVC4_ASSERTIONS
+ TS_ASSERT_THROWS(d_nm->mkNode(XOR, y, x, x), AssertionException);
+#endif /* CVC4_ASSERTIONS */
+
NodeBuilder<> b;
// test append(TNode)
}
};
-class DummyTheory : public TheoryImpl<DummyTheory> {
+class DummyTheory : public Theory {
public:
set<Node> d_registered;
vector<Node> d_getSequence;
DummyTheory(Context* ctxt, OutputChannel& out) :
- TheoryImpl<DummyTheory>(ctxt, out) {
+ Theory(ctxt, out) {
}
void registerTerm(TNode n) {