/*****************************************************************************/ /*! * \file expr_value.h * * Author: Sergey Berezin * * Created: Fri Feb 7 15:07:18 2003 * *
* * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. * *
* * Class ExprValue: the value holding class of Expr. No one should * use it directly; use Expr API instead. To enforce that, the * constructors are made protected, and only Expr, ExprManager, and * subclasses can use them. */ /*****************************************************************************/ // *** HACK ATTACK *** (trick from Aaron Stump's code) // In order to inline the Expr constructors (for efficiency), this // file (expr_value.h) must be included in expr.h. However, we also // need to include expr.h here, hence, circular dependency. A way to // break it is to include expr_value.h in the middle of expr.h after // the definition of class Expr, but before the definition of its // inlined methods. So, expr.h included below will also suck in // expr_value.h recursively, meaning that we then should skip the rest // of the file (since it's already been included). // That's why expr.h is outside of #ifndef. The same is true for // type.h and theorem.h. #ifndef _cvc3__expr_h_ #include "expr.h" #endif #ifndef _cvc3__expr_value_h_ #define _cvc3__expr_value_h_ #include "theorem.h" #include "type.h" // The prime number used in the hash function for a vector of elements #define PRIME 131 namespace CVC3 { /*****************************************************************************/ /*! *\class ExprValue *\brief The base class for holding the actual data in expressions * * * Author: Sergey Berezin * * Created: long time ago * * \anchor ExprValue The base class just holds the operator. * All the additional data resides in subclasses. * */ /*****************************************************************************/ class ExprValue { friend class Expr; friend class Expr::iterator; friend class ExprManager; friend class ::CInterface; friend class ExprApply; friend class Theorem; //! Unique expression id ExprIndex d_index; //! Reference counter for garbage collection unsigned d_refcount; //! Cached hash value (initially 0) size_t d_hash; //! The find attribute (may be NULL) CDO* d_find; //! The cached type of the expression (may be Null) Type d_type; //! The cached TCC of the expression (may be Null) // Expr d_tcc; //! Subtyping predicate for the expression and all subexpressions // Theorem d_subtypePred; //! Notify list may be NULL (== no such attribute) NotifyList* d_notifyList; //! For caching calls to Simplify Theorem d_simpCache; //! For checking whether simplify cache is valid unsigned d_simpCacheTag; //! context-dependent bit-vector for flags that are context-dependent CDFlags d_dynamicFlags; //! Height of this expression // int d_height; //! Which child has the largest height // int d_highestKid; //! Most distant expression we were simplified *from* // Expr d_simpFrom; //! Generic flag for marking expressions (e.g. in DAG traversal) unsigned d_flag; protected: /*! @brief The kind of the expression. In particular, it determines which * subclass of ExprValue is used to store the expression. */ int d_kind; //! Our expr. manager ExprManager* d_em; // End of data members private: //! Set the ExprIndex void setIndex(ExprIndex idx) { d_index = idx; } //! Increment reference counter void incRefcount() { ++d_refcount; } //! Decrement reference counter void decRefcount() { // Cannot be DebugAssert, since we are called in a destructor // and should not throw an exception FatalAssert(d_refcount > 0, "Mis-handled the ref. counting"); if((--d_refcount) == 0) d_em->gc(this); } //! Caching hash function /*! Do NOT implement it in subclasses! Implement computeHash() instead. */ size_t hash() const { if(d_hash == 0) const_cast(this)->d_hash = computeHash(); return d_hash; } //! Return height of Expr // int getHeight() const { return d_height; } //! Return child with greatest height // int getHighestKid() const { return d_highestKid; } //! Get Expr simplified to obtain this expr // const Expr& getSimpFrom() const { return d_simpFrom; } //! Set Expr simplified to obtain this expr // void setSimpFrom(const Expr& simpFrom) { d_simpFrom = simpFrom; } protected: // Static hash functions. They don't depend on the context // (ExprManager and such), so it is still thread-safe to have them // static. static std::hash s_charHash; static std::hash s_intHash; static size_t pointerHash(void* p) { return s_intHash((long int)p); } // Hash function for subclasses with children static size_t hash(const int kind, const std::vector& kids); // Hash function for kinds static size_t hash(const int n) { return s_intHash((long int)n); } //! Return the memory manager (for the benefit of subclasses) MemoryManager* getMM(size_t MMIndex) { DebugAssert(d_em!=NULL, "ExprValue::getMM()"); return d_em->getMM(MMIndex); } //! Make a clean copy of itself using the given ExprManager ExprValue* rebuild(ExprManager* em) const { return copy(em, 0); } //! Make a clean copy of the expr using the given ExprManager Expr rebuild(Expr e, ExprManager* em) const { return em->rebuildRec(e); } // Protected API //! Non-caching hash function which actually computes the hash. /*! This is the method that all subclasses should implement */ virtual size_t computeHash() const { return hash(d_kind); } //! Make a clean copy of itself using the given ExprManager virtual ExprValue* copy(ExprManager* em, ExprIndex idx) const; public: //! Constructor ExprValue(ExprManager* em, int kind, ExprIndex idx = 0) : d_index(idx), d_refcount(0), d_hash(0), d_find(NULL), d_notifyList(NULL), d_simpCacheTag(0), d_dynamicFlags(em->getCurrentContext()), // d_height(0), d_highestKid(-1), d_flag(0), d_kind(kind), d_em(em) { DebugAssert(em != NULL, "NULL ExprManager is given to ExprValue()"); DebugAssert(em->isKindRegistered(kind), ("ExprValue(kind = " + int2string(kind) + ")): kind is not registered").c_str()); DebugAssert(kind != APPLY, "Only ExprApply should have APPLY kind"); // #ifdef DEBUG //added by yeting, just hold a place to put my breakpoints in gdb // if(idx != 0){ // TRACE("expr", "expr created ", idx, "");//the line added by yeting // // char * a; // // a="a"; // // a[999999]=255; // } // #endif } //! Destructor virtual ~ExprValue(); //! Get the kind of the expression int getKind() const { return d_kind; } //! Overload operator new void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } //! Overload operator delete void operator delete(void*) { } //! Get unique memory manager ID virtual size_t getMMIndex() const { return EXPR_VALUE; } //! Equality between any two ExprValue objects (including subclasses) virtual bool operator==(const ExprValue& ev2) const; // Testers //! Test whether the expression is a generic subclass /*! * \return 0 for the core classes, and getMMIndex() value for * generic subclasses (those defined in DPs) */ virtual const ExprValue* getExprValue() const { throw Exception("Illegal call to getExprValue()"); } //! String expression tester virtual bool isString() const { return false; } //! Rational number expression tester virtual bool isRational() const { return false; } //! Uninterpreted constants virtual bool isVar() const { return false; } //! Application of another expression virtual bool isApply() const { return false; } //! Special named symbol virtual bool isSymbol() const { return false; } //! A LAMBDA-expression or a quantifier virtual bool isClosure() const { return false; } //! Special Expr holding a theorem virtual bool isTheorem() const { return false; } //! Get kids: by default, returns a ref to an empty vector virtual const std::vector& getKids() const { return d_em->getEmptyVector(); } // Methods to access leaf data in subclasses //! Default arity = 0 virtual unsigned arity() const { return 0; } //! Special attributes for uninterpreted functions virtual CDO* getSig() const { DebugAssert(false, "getSig() is called on ExprValue"); return NULL; } virtual CDO* getRep() const { DebugAssert(false, "getRep() is called on ExprValue"); return NULL; } virtual void setSig(CDO* sig) { DebugAssert(false, "setSig() is called on ExprValue"); } virtual void setRep(CDO* rep) { DebugAssert(false, "setRep() is called on ExprValue"); } virtual const std::string& getUid() const { static std::string null; DebugAssert(false, "ExprValue::getUid() called in base class"); return null; } virtual const std::string& getString() const { DebugAssert(false, "getString() is called on ExprValue"); static std::string s(""); return s; } virtual const Rational& getRational() const { DebugAssert(false, "getRational() is called on ExprValue"); static Rational r(0); return r; } //! Returns the string name of UCONST and BOUND_VAR expr's. virtual const std::string& getName() const { static std::string ret = ""; DebugAssert(false, "getName() is called on ExprValue"); return ret; } //! Returns the original Boolean variable (for BoolVarExprValue) virtual const Expr& getVar() const { DebugAssert(false, "getVar() is called on ExprValue"); static Expr null; return null; } //! Get the Op from an Apply Expr virtual Op getOp() const { DebugAssert(false, "getOp() is called on ExprValue"); return Op(NULL_KIND); } virtual const std::vector& getVars() const { DebugAssert(false, "getVars() is called on ExprValue"); static std::vector null; return null; } virtual const Expr& getBody() const { DebugAssert(false, "getBody() is called on ExprValue"); static Expr null; return null; } virtual const Expr& getExistential() const { DebugAssert(false, "getExistential() is called on ExprValue"); static Expr null; return null; } virtual int getBoundIndex() const { DebugAssert(false, "getIndex() is called on ExprValue"); return 0; } virtual const std::vector& getFields() const { DebugAssert(false, "getFields() is called on ExprValue"); static std::vector null; return null; } virtual const std::string& getField() const { DebugAssert(false, "getField() is called on ExprValue"); static std::string null; return null; } virtual int getTupleIndex() const { DebugAssert(false, "getTupleIndex() is called on ExprValue"); return 0; } virtual const Theorem& getTheorem() const { static Theorem null; DebugAssert(false, "getTheorem() is called on ExprValue"); return null; } }; // end of class ExprValue // Class ExprNode; it's an expression with children class ExprNode: public ExprValue { friend class Expr; friend class ExprManager; protected: //! Vector of children std::vector d_children; // Special attributes for helping with congruence closure CDO* d_sig; CDO* d_rep; private: //! Tell ExprManager who we are size_t getMMIndex() const { return EXPR_NODE; } protected: //! Return number of children unsigned arity() const { return d_children.size(); } //! Return reference to children std::vector& getKids1() { return d_children; } //! Return reference to children const std::vector& getKids() const { return d_children; } //! Use our static hash() for the member method size_t computeHash() const { return ExprValue::hash(d_kind, d_children); } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: //! Constructor ExprNode(ExprManager* em, int kind, ExprIndex idx = 0) : ExprValue(em, kind, idx), d_sig(NULL), d_rep(NULL) { } //! Constructor ExprNode(ExprManager* em, int kind, const std::vector& kids, ExprIndex idx = 0) : ExprValue(em, kind, idx), d_children(kids), d_sig(NULL), d_rep(NULL) { } //! Destructor virtual ~ExprNode(); //! Overload operator new void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } //! Overload operator delete void operator delete(void*) { } //! Compare with another ExprValue virtual bool operator==(const ExprValue& ev2) const; virtual CDO* getSig() const { return d_sig; } virtual CDO* getRep() const { return d_rep; } virtual void setRep(CDO* rep) { d_rep = rep; } virtual void setSig(CDO* sig) { d_sig = sig; } }; // end of class ExprNode // Class ExprNodeTmp; special version of ExprNode for Expr constructor class ExprNodeTmp: public ExprValue { friend class Expr; friend class ExprManager; protected: //! Vector of children const std::vector& d_children; private: //! Tell ExprManager who we are size_t getMMIndex() const { return EXPR_NODE; } protected: //! Return number of children unsigned arity() const { return d_children.size(); } //! Return reference to children const std::vector& getKids() const { return d_children; } //! Use our static hash() for the member method size_t computeHash() const { return ExprValue::hash(d_kind, d_children); } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: //! Constructor ExprNodeTmp(ExprManager* em, int kind, const std::vector& kids) : ExprValue(em, kind, 0), d_children(kids) { } //! Destructor virtual ~ExprNodeTmp() {} //! Compare with another ExprValue virtual bool operator==(const ExprValue& ev2) const; }; // end of class ExprNodeTmp // Special version for Expr Constructor class ExprApplyTmp: public ExprNodeTmp { friend class Expr; friend class ExprManager; private: Expr d_opExpr; protected: size_t getMMIndex() const { return EXPR_APPLY; } size_t computeHash() const { return PRIME*ExprNodeTmp::computeHash() + d_opExpr.hash(); } Op getOp() const { return Op(d_opExpr); } bool isApply() const { return true; } // Make a clean copy of itself using the given memory manager ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: // Constructor ExprApplyTmp(ExprManager* em, const Op& op, const std::vector& kids) : ExprNodeTmp(em, NULL_KIND, kids), d_opExpr(op.getExpr()) { DebugAssert(!op.getExpr().isNull(), "Expected non-null Op"); d_kind = APPLY; } virtual ~ExprApplyTmp() { } bool operator==(const ExprValue& ev2) const; }; // end of class ExprApply class CVC_DLL ExprApply: public ExprNode { friend class Expr; friend class ExprManager; private: Expr d_opExpr; protected: size_t getMMIndex() const { return EXPR_APPLY; } size_t computeHash() const { return PRIME*ExprNode::computeHash() + d_opExpr.hash(); } Op getOp() const { return Op(d_opExpr); } bool isApply() const { return true; } // Make a clean copy of itself using the given memory manager ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: // Constructor ExprApply(ExprManager* em, const Op& op, ExprIndex idx = 0) : ExprNode(em, NULL_KIND, idx), d_opExpr(op.getExpr()) { DebugAssert(!op.getExpr().isNull(), "Expected non-null Op"); d_kind = APPLY; } ExprApply(ExprManager* em, const Op& op, const std::vector& kids, ExprIndex idx = 0) : ExprNode(em, NULL_KIND, kids, idx), d_opExpr(op.getExpr()) { DebugAssert(!op.getExpr().isNull(), "Expected non-null Op"); d_kind = APPLY; } virtual ~ExprApply() { } bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprApply /*****************************************************************************/ /*! *\class NamedExprValue *\brief NamedExprValue * * Author: Clark Barrett * * Created: Thu Dec 2 23:18:17 2004 * * Subclass of ExprValue for kinds that have a name associated with them. */ /*****************************************************************************/ // class NamedExprValue : public ExprNode { // friend class Expr; // friend class ExprManager; // private: // std::string d_name; // protected: // ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const { // return new(em->getMM(getMMIndex())) // NamedExprValue(d_em, d_kind, d_name, d_children, idx); // } // ExprValue* copy(ExprManager* em, const std::vector& kids, // ExprIndex idx = 0) const { // return new(em->getMM(getMMIndex())) // NamedExprValue(d_em, d_kind, d_name, kids, idx); // } // size_t computeHash() const { // return s_charHash(d_name.c_str())*PRIME + ExprNode::computeHash(); // } // size_t getMMIndex() const { return EXPR_NAMED; } // public: // // Constructor // NamedExprValue(ExprManager *em, int kind, const std::string& name, // const std::vector& kids, ExprIndex idx = 0) // : ExprNode(em, kind, kids, idx), d_name(name) { } // // virtual ~NamedExprValue(); // bool operator==(const ExprValue& ev2) const { // if(getMMIndex() != ev2.getMMIndex()) return false; // return (getName() == ev2.getName()) // && ExprNode::operator==(ev2); // } // const std::string& getName() const { return d_name; } // // Memory management // void* operator new(size_t size, MemoryManager* mm) { // return mm->newData(size); // } // void operator delete(void*) { } // }; // end of class NamedExprValue // Leaf expressions class ExprString: public ExprValue { friend class Expr; friend class ExprManager; private: std::string d_str; // Hash function for this subclass static size_t hash(const std::string& str) { return s_charHash(str.c_str()); } // Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_STRING; } protected: // Use our static hash() for the member method virtual size_t computeHash() const { return hash(d_str); } virtual bool isString() const { return true; } virtual const std::string& getString() const { return d_str; } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: // Constructor ExprString(ExprManager* em, const std::string& s, ExprIndex idx = 0) : ExprValue(em, STRING_EXPR, idx), d_str(s) { } // Destructor virtual ~ExprString() { } virtual bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprString class ExprSkolem: public ExprValue { friend class Expr; friend class ExprManager; private: Expr d_quant; //!< The quantified expression to skolemize int d_idx; //!< Variable index in the quantified expression const Expr& getExistential() const {return d_quant;} int getBoundIndex() const {return d_idx;} // Tell ExprManager who we are size_t getMMIndex() const { return EXPR_SKOLEM;} protected: size_t computeHash() const { size_t res = getExistential().getBody().hash(); res = PRIME*res + getBoundIndex(); return res; } bool operator==(const ExprValue& ev2) const; //! Make a clean copy of itself using the given memory manager ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; bool isVar() const { return true; } public: // Constructor ExprSkolem(ExprManager* em, int index, const Expr& exist, ExprIndex idx = 0) : ExprValue(em, SKOLEM_VAR, idx), d_quant(exist), d_idx(index) { } // Destructor virtual ~ExprSkolem() { } // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprSkolem class ExprRational: public ExprValue { friend class Expr; friend class ExprManager; private: Rational d_r; virtual const Rational& getRational() const { return d_r; } // Hash function for this subclass static size_t hash(const Rational& r) { return s_charHash(r.toString().c_str()); } // Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_RATIONAL; } protected: virtual size_t computeHash() const { return hash(d_r); } virtual bool operator==(const ExprValue& ev2) const; //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; virtual bool isRational() const { return true; } public: // Constructor ExprRational(ExprManager* em, const Rational& r, ExprIndex idx = 0) : ExprValue(em, RATIONAL_EXPR, idx), d_r(r) { } // Destructor virtual ~ExprRational() { } // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprRational // Uninterpreted constants (variables) class ExprVar: public ExprValue { friend class Expr; friend class ExprManager; private: std::string d_name; virtual const std::string& getName() const { return d_name; } // Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_UCONST; } protected: virtual size_t computeHash() const { return s_charHash(d_name.c_str()); } virtual bool isVar() const { return true; } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: // Constructor ExprVar(ExprManager *em, const std::string& name, ExprIndex idx = 0) : ExprValue(em, UCONST, idx), d_name(name) { } // Destructor virtual ~ExprVar() { } virtual bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprVar // Interpreted symbols: similar to UCONST, but returns false for isVar(). class ExprSymbol: public ExprValue { friend class Expr; friend class ExprManager; private: std::string d_name; virtual const std::string& getName() const { return d_name; } // Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_SYMBOL; } protected: virtual size_t computeHash() const { return s_charHash(d_name.c_str())*PRIME + s_intHash(d_kind); } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; bool isSymbol() const { return true; } public: // Constructor ExprSymbol(ExprManager *em, int kind, const std::string& name, ExprIndex idx = 0) : ExprValue(em, kind, idx), d_name(name) { } // Destructor virtual ~ExprSymbol() { } virtual bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprSymbol class ExprBoundVar: public ExprValue { friend class Expr; friend class ExprManager; private: std::string d_name; std::string d_uid; virtual const std::string& getName() const { return d_name; } virtual const std::string& getUid() const { return d_uid; } // Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_BOUND_VAR; } protected: virtual size_t computeHash() const { return s_charHash(d_name.c_str())*PRIME + s_charHash(d_uid.c_str()); } virtual bool isVar() const { return true; } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: // Constructor ExprBoundVar(ExprManager *em, const std::string& name, const std::string& uid, ExprIndex idx = 0) : ExprValue(em, BOUND_VAR, idx), d_name(name), d_uid(uid) { } // Destructor virtual ~ExprBoundVar() { } virtual bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; // end of class ExprBoundVar /*! @brief A "closure" expression which binds variables used in the "body". Used by LAMBDA and quantifiers. */ class ExprClosure: public ExprValue { friend class Expr; friend class ExprManager; private: //! Bound variables std::vector d_vars; //! The body of the quantifier/lambda Expr d_body; //! Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_CLOSURE; } virtual const std::vector& getVars() const { return d_vars; } virtual const Expr& getBody() const { return d_body; } protected: size_t computeHash() const; //! Make a clean copy of itself using the given memory manager ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; public: // Constructor ExprClosure(ExprManager *em, int kind, const std::vector& vars, const Expr& body, ExprIndex idx = 0) : ExprValue(em, kind, idx), d_vars(vars), d_body(body) { } // Destructor virtual ~ExprClosure() { } bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } virtual bool isClosure() const { return true; } }; // end of class ExprClosure // Expr that stores a theorem class ExprTheorem: public ExprValue { friend class Expr; friend class ExprManager; private: Theorem d_thm; virtual const Theorem& getTheorem() const { return d_thm; } // Tell ExprManager who we are virtual size_t getMMIndex() const { return EXPR_THEOREM; } protected: virtual size_t computeHash() const { return d_thm.hash(); } //! Make a clean copy of itself using the given memory manager virtual ExprValue* copy(ExprManager* em, ExprIndex idx = 0) const; bool isTheorem() const { return true; } public: // Constructor ExprTheorem(ExprManager *em, const Theorem& thm, ExprIndex idx = 0) : ExprValue(em, THEOREM_KIND, idx), d_thm(thm) { } // Destructor virtual ~ExprTheorem() { } virtual bool operator==(const ExprValue& ev2) const; // Memory management void* operator new(size_t size, MemoryManager* mm) { return mm->newData(size); } void operator delete(void* pMem, MemoryManager* mm) { mm->deleteData(pMem); } void operator delete(void*) { } }; } // end of namespace CVC3 #endif