expr.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file expr.h
00004  * \brief Definition of the API to expression package.  See class Expr for details.
00005  * 
00006  * Author: Clark Barrett
00007  * 
00008  * Created: Tue Nov 26 00:27:40 2002
00009  *
00010  * <hr>
00011  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00012  * Junior University and by New York University. 
00013  *
00014  * License to use, copy, modify, sell and/or distribute this software
00015  * and its documentation for any purpose is hereby granted without
00016  * royalty, subject to the terms and conditions defined in the \ref
00017  * LICENSE file provided with this distribution.  In particular:
00018  *
00019  * - The above copyright notice and this permission notice must appear
00020  * in all copies of the software and related documentation.
00021  *
00022  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00023  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00024  * 
00025  * <hr>
00026  * 
00027  */
00028 /*****************************************************************************/
00029 
00030 #ifndef _CVC_lite__expr_h_
00031 #define _CVC_lite__expr_h_
00032 
00033 #include <stdlib.h>
00034 #include <sstream>
00035 #include <set>
00036 #include <functional>
00037 #include <iterator>
00038 #include <map>
00039 
00040 #include "compat_hash_map.h"
00041 #include "compat_hash_set.h"
00042 #include "rational.h"
00043 #include "kinds.h"
00044 #include "cdo.h"
00045 #include "cdflags.h"
00046 #include "lang.h"
00047 #include "memory_manager.h"
00048 
00049 class CInterface;
00050 
00051 namespace CVCL {
00052 
00053   class NotifyList;
00054   class Theory;
00055   class Op;
00056   class Type;
00057   class Theorem;
00058 
00059   template<class Data>
00060   class ExprHashMap;
00061 
00062   class ExprManager;
00063   // Internal data-holding classes
00064   class ExprValue;
00065   class ExprNode;
00066   // Printing
00067   class ExprStream;
00068 
00069   //! Type ID of each ExprValue subclass.
00070   /*! It is defined in expr.h, so that ExprManager can use it before loading
00071     expr_value.h */
00072   typedef enum {
00073     EXPR_VALUE,
00074     EXPR_NODE,
00075     EXPR_APPLY, //!< Application of functions and predicates
00076     EXPR_STRING,
00077     EXPR_RATIONAL,
00078     EXPR_SKOLEM,
00079     EXPR_UCONST,
00080     EXPR_SYMBOL,
00081     EXPR_BOUND_VAR,
00082     EXPR_CLOSURE,
00083     EXPR_VALUE_TYPE_LAST // The end of list; don't assign it to any subclass
00084   } ExprValueType;
00085 
00086   //! Expression index type
00087   typedef long long unsigned ExprIndex;
00088 
00089   /**************************************************************************/
00090   /*! \defgroup ExprPkg Expression Package
00091    * \ingroup BuildingBlocks
00092    */
00093   /**************************************************************************/
00094   /*! \defgroup Expr_SmartPointer Smart Pointer Functionality in Expr
00095    * \ingroup ExprPkg
00096    */
00097   /**************************************************************************/
00098 
00099   /**************************************************************************/
00100   //! Data structure of expressions in CVC Lite
00101   /*! \ingroup ExprPkg
00102    * Class: Expr <br>
00103    * Author: Clark Barrett <br>
00104    * Created: Mon Nov 25 15:29:37 2002
00105    *
00106    * This class is the main data structure for expressions that all
00107    * other components should use.  It is actually a <em>smart
00108    * pointer</em> to the actual data holding class ExprValue and its
00109    * subclasses.
00110    *
00111    * Expressions are represented as DAGs with maximal sharing of
00112    * subexpressions.  Therefore, testing for equality is a constant time
00113    * operation (simply compare the pointers).
00114    *
00115    * Unused expressions are automatically garbage-collected.  The use is
00116    * determined by a reference counting mechanism.  In particular, this
00117    * means that if there is a circular dependency among expressions
00118    * (e.g. an attribute points back to the expression itself), these
00119    * expressions will not be garbage-collected, even if no one else is
00120    * using them.
00121    *
00122    * The most frequently used operations are getKind() (determining the
00123    * kind of the top level node of the expression), arity() (how many
00124    * children an Expr has), operator[]() for accessing a child, and
00125    * various testers and methods for constructing new expressions.
00126    *
00127    * In addition, a total ordering operator<() is provided.  It is
00128    * guaranteed to remain the same for the lifetime of the expressions
00129    * (it may change, however, if the expression is garbage-collected and
00130    * reborn).
00131    */
00132   /**************************************************************************/
00133 class Expr {
00134   friend class ExprHasher;
00135   friend class ExprManager;
00136   friend class Op;
00137   friend class ExprValue;
00138   friend class ExprNode;
00139   friend class ::CInterface;
00140 
00141   /*! \addtogroup ExprPkg
00142    * @{
00143    */
00144   //! bit-masks for static flags
00145   typedef enum {
00146     //! Whether is valid TYPE expr
00147     VALID_TYPE = 0x1,
00148     //! Whether IS_ATOMIC flag is valid (initialized)
00149     VALID_IS_ATOMIC = 0x2,
00150     //! Whether the expression is an atomic term or formula
00151     IS_ATOMIC = 0x4,
00152     //! Expression is the result of a "normal" (idempotent) rewrite
00153     REWRITE_NORMAL = 0x8,
00154     //! Finite type
00155     IS_FINITE = 0x400,
00156     //! Well-founded (used in datatypes)
00157     WELL_FOUNDED = 0x800,
00158     //! Compute transitive closure (for binary uninterpreted predicates)
00159     COMPUTE_TRANS_CLOSURE = 0x1000
00160   } StaticFlagsEnum;
00161 
00162   //! bit-masks for dynamic flags
00163   // TODO: Registered flags instead of hard-wired
00164   typedef enum {
00165     //! Whether expr has been added as an implied literal
00166     IMPLIED_LITERAL = 0x10,
00167     IS_USER_ASSUMPTION = 0x20,
00168     IS_INT_ASSUMPTION = 0x40,
00169     IS_JUSTIFIED = 0x80,
00170     IS_TRANSLATED = 0x100,
00171     IS_USER_REGISTERED_ATOM = 0x200,
00172     IS_SELECTED = 0x2000
00173   } DynamicFlagsEnum;
00174 
00175   //! Convenient null expr
00176   static Expr s_null;
00177 
00178   /////////////////////////////////////////////////////////////////////////////
00179   // Private Dynamic Data                                                    //
00180   /////////////////////////////////////////////////////////////////////////////
00181   //! The value.  This is the only data member in this class.
00182   ExprValue* d_expr;
00183 
00184   /////////////////////////////////////////////////////////////////////////////
00185   // Private methods                                                         //
00186   /////////////////////////////////////////////////////////////////////////////
00187 
00188   //! Private constructor, simply wraps around the pointer
00189   Expr(ExprValue* expr);
00190 
00191   Expr recursiveSubst(const ExprHashMap<Expr>& subst,
00192                       ExprHashMap<Expr>& visited) const;
00193 public:
00194   /////////////////////////////////////////////////////////////////////////////
00195   // Public Classes and Types                                                //
00196   /////////////////////////////////////////////////////////////////////////////
00197 
00198   /////////////////////////////////////////////////////////////////////////////
00199   /*!
00200    * Class: Expr::iterator
00201    * Author: Sergey Berezin
00202    * Created: Fri Dec  6 15:38:51 2002
00203    * Description: STL-like iterator API to the Expr's children.
00204    * IMPORTANT: the iterator will not be valid after the originating 
00205    * expression is destroyed.
00206   */
00207   /////////////////////////////////////////////////////////////////////////////
00208   class iterator
00209     : public std::iterator<std::input_iterator_tag,Expr,ptrdiff_t>
00210   {
00211     friend class Expr;
00212   private:
00213     std::vector<Expr>::const_iterator d_it;
00214     // Private constructors (used by Expr only)
00215     //
00216     //! Construct an iterator out of the vector's iterator
00217     iterator(std::vector<Expr>::const_iterator it): d_it(it) { }
00218     // Public methods
00219   public:
00220     //! Default constructor
00221     iterator() { }
00222     // Copy constructor and operator= are defined by C++, that's good enough
00223 
00224     //! Equality
00225     bool operator==(const iterator& i) const {
00226       return d_it == i.d_it;
00227     }
00228     //! Disequality
00229     bool operator!=(const iterator& i) const { return !(*this == i); }
00230     //! Dereference operator
00231     const Expr& operator*() const;
00232     //! Dereference and member access
00233     const Expr* operator->() const;
00234     //! Prefix increment
00235     iterator& operator++() {
00236       d_it++;
00237       return *this;
00238     }
00239     /*! @brief Postfix increment requires a Proxy object to hold the
00240      * intermediate value for dereferencing */
00241     class Proxy {
00242       const Expr* d_e;
00243     public:
00244       Proxy(const Expr& e) : d_e(&e) { }
00245       Expr operator*() { return *d_e; }
00246     };
00247     //! Postfix increment
00248     /*! \return Proxy with the old Expr.
00249      *
00250      * Now, an expression like *i++ will return the current *i, and
00251      * then advance the iterator.  However, don't try to use Proxy for
00252      * anything else. 
00253      */
00254     Proxy operator++(int) {
00255       Proxy e(*(*this));
00256       ++(*this);
00257       return e;
00258     }
00259   }; // end of class Expr::iterator
00260 
00261   /////////////////////////////////////////////////////////////////////////////
00262   // Constructors                                                            //
00263   /////////////////////////////////////////////////////////////////////////////
00264 
00265   //! Default constructor creates the Null Expr
00266   Expr(): d_expr(NULL) {}
00267 
00268   /*! @brief Copy constructor and assignment (copy the pointer and take care
00269     of the refcount) */
00270   Expr(const Expr& e);
00271   //! Assignment operator: take care of the refcounting and GC
00272   Expr& operator=(const Expr& e);
00273 
00274   // These constructors grab the ExprManager from the Op or the first
00275   // child.  The operator and all children must belong to the same
00276   // ExprManager.
00277   Expr(const Op& op, const Expr& child);
00278   Expr(const Op& op, const Expr& child0, const Expr& child1);
00279   Expr(const Op& op, const Expr& child0, const Expr& child1,
00280        const Expr& child2);
00281   Expr(const Op& op, const Expr& child0, const Expr& child1,
00282        const Expr& child2, const Expr& child3);
00283   Expr(const Op& op, const std::vector<Expr>& children,
00284        ExprManager* em = NULL);
00285 
00286   //! Destructor
00287   ~Expr();
00288 
00289   // Compound expression constructors
00290   Expr eqExpr(const Expr& right) const;
00291   Expr notExpr() const;
00292   Expr negate() const; // avoid double-negatives
00293   Expr andExpr(const Expr& right) const;
00294   Expr orExpr(const Expr& right) const;
00295   Expr iteExpr(const Expr& thenpart, const Expr& elsepart) const;
00296   Expr iffExpr(const Expr& right) const;
00297   Expr impExpr(const Expr& right) const;
00298   //! Create a Skolem constant for the i'th variable of an existential (*this)
00299   Expr skolemExpr(int i) const;
00300   //! Create a Boolean variable out of the expression
00301   //  Expr boolVarExpr() const;
00302   //! Rebuild Expr with a new ExprManager
00303   Expr rebuild(ExprManager* em) const;
00304 //    Expr newForall(const Expr& e);
00305 //    Expr newExists(const Expr& e);
00306   Expr substExpr(const std::vector<Expr>& oldTerms,
00307                  const std::vector<Expr>& newTerms) const;
00308   Expr substExpr(const ExprHashMap<Expr>& oldToNew) const;
00309 
00310   Expr operator!() const { return notExpr(); }
00311   Expr operator&&(const Expr& right) const { return andExpr(right); }
00312   Expr operator||(const Expr& right) const { return orExpr(right); }
00313 
00314   /////////////////////////////////////////////////////////////////////////////
00315   // Public Static Methods                                                   //
00316   /////////////////////////////////////////////////////////////////////////////
00317 
00318   static size_t hash(const Expr& e);
00319 
00320   /////////////////////////////////////////////////////////////////////////////
00321   // Read-only (const) methods                                               //
00322   /////////////////////////////////////////////////////////////////////////////
00323 
00324   size_t hash() const;
00325 
00326   // Core expression testers
00327 
00328   bool isFalse() const { return getKind() == FALSE; }
00329   bool isTrue() const { return getKind() == TRUE; }
00330   bool isBoolConst() const { return isFalse() || isTrue(); }
00331   bool isVar() const;
00332   bool isBoundVar() const { return getKind() == BOUND_VAR; }
00333   bool isString() const;
00334   bool isClosure() const;
00335   bool isQuantifier() const;
00336   bool isLambda() const;
00337   bool isApply() const;
00338   bool isSymbol() const;
00339   //! Expr represents a type
00340   bool isType() const;
00341   /*
00342   bool isRecord() const;
00343   bool isRecordAccess() const;
00344   bool isTupleAccess() const;
00345   */
00346   //! Provide access to ExprValue for client subclasses of ExprValue *only*
00347   /*@ Calling getExprValue on an Expr with a built-in ExprValue class will
00348    * cause an error */
00349   const ExprValue* getExprValue() const;
00350 
00351   //! Test if e is a term (as opposed to a predicate/formula)
00352   bool isTerm() const;
00353   //! Test if e is atomic
00354   /*! An atomic expression is one that does not contain a formula (including
00355    *  not being a formula itself).
00356    *  \sa isAtomicFormula */
00357   bool isAtomic() const;
00358   //! Test if e is an atomic formula
00359   /*! An atomic formula is TRUE or FALSE or an application of a predicate
00360     (possibly 0-ary) which does not properly contain any formula.  For
00361     instance, the formula "x = IF f THEN y ELSE z ENDIF is not an atomic
00362     formula, since it contains the condition "f", which is a formula. */
00363   bool isAtomicFormula() const;
00364   //! An abstract atomic formua is an atomic formula or a quantified formula
00365   bool isAbsAtomicFormula() const
00366     { return isQuantifier() || isAtomicFormula(); }
00367   //! Test if e is a literal
00368   /*! A literal is an atomic formula, or its negation.  
00369     \sa isAtomicFormula */
00370   bool isLiteral() const
00371   { return (isAtomicFormula() || (isNot() && (*this)[0].isAtomicFormula())); }
00372   //! Test if e is an abstract literal
00373   bool isAbsLiteral() const
00374   { return (isAbsAtomicFormula() || (isNot() && (*this)[0].isAbsAtomicFormula())); }
00375   //! A Bool connective is one of NOT,AND,OR,IMPLIES,IFF,XOR,ITE (with type Bool)
00376   bool isBoolConnective() const;
00377   //! True iff expr is not a Bool connective
00378   bool isPropAtom() const { return !isBoolConnective(); }
00379   //! PropAtom or negation of PropAtom
00380   bool isPropLiteral() const
00381     { return (isNot() && (*this)[0].isPropAtom()) || isPropAtom(); }
00382 
00383   bool isEq() const { return getKind() == EQ; }
00384   bool isNot() const { return getKind() == NOT; }
00385   bool isAnd() const { return getKind() == AND; }
00386   bool isOr() const { return getKind() == OR; }
00387   bool isITE() const { return getKind() == ITE; }
00388   bool isIff() const { return getKind() == IFF; }
00389   bool isImpl() const { return getKind() == IMPLIES; }
00390   bool isXor() const { return getKind() == XOR;}
00391 
00392   bool isForall() const { return getKind() == FORALL; }
00393   bool isExists() const { return getKind() == EXISTS; }
00394 
00395   bool isRational() const { return getKind() == RATIONAL_EXPR; }
00396   bool isSkolem() const { return getKind() == SKOLEM_VAR;}
00397 
00398   // Leaf accessors - these functions must only be called one expressions of
00399   // the appropriate kind.
00400 
00401   // For UCONST and BOUND_VAR Expr's
00402   const std::string& getName() const;
00403   //! For BOUND_VAR, get the UID
00404   const std::string& getUid() const;
00405 
00406   // For STRING_EXPR's
00407   const std::string& getString() const; 
00408   //! Get bound variables from a closure Expr
00409   const std::vector<Expr>& getVars() const;
00410   //! Get the existential axiom expression for skolem constant
00411   const Expr& getExistential() const;
00412   //! Get the index of the bound var that skolem constant comes from
00413   int getBoundIndex() const;
00414  
00415   //! Get the body of the closure Expr
00416   const Expr& getBody() const;
00417   //! Get the Rational value out of RATIONAL_EXPR
00418   const Rational& getRational() const; 
00419 
00420   // Get the expression manager.  The expression must be non-null.
00421   ExprManager *getEM() const;
00422 
00423   // Return a ref to the vector of children.
00424   const std::vector<Expr>& getKids() const;
00425 
00426   // Get the kind of this expr.
00427   int getKind() const;
00428 
00429   // Get the index field
00430   ExprIndex getIndex() const;
00431 
00432   // True if this is the most recently created expression
00433   bool hasLastIndex() const;
00434 
00435   //! Make the expr into an operator
00436   Op mkOp() const;
00437 
00438   //! Get operator from expression
00439   Op getOp() const;
00440 
00441   //! Get expression of operator (for APPLY Exprs only)
00442   Expr getOpExpr() const;
00443 
00444   //! Get kind of operator (for APPLY Exprs only)
00445   int getOpKind() const;
00446 
00447   // Return the number of children.  Note, that an application of a
00448   // user-defined function has the arity of that function (the number
00449   // of arguments), and the function name itself is part of the
00450   // operator.
00451   int arity() const;
00452 
00453   // Return the ith child.  As with arity, it's also the ith argument
00454   // in function application.
00455   const Expr& operator[](int i) const;
00456 
00457   //! Remove leading NOT if any
00458   const Expr& unnegate() const { return isNot() ? (*this)[0] : *this; }
00459 
00460   //! Begin iterator
00461   iterator begin() const;
00462   //! End iterator
00463   iterator end() const;
00464 
00465   // Check if Expr is Null
00466   bool isNull() const;
00467 
00468   // Check if Expr is not Null
00469   bool isInitialized() const { return d_expr != NULL; }
00470   //! Get the memory manager index (it uniquely identifies the subclass)
00471   size_t getMMIndex() const;
00472 
00473   // Attributes
00474 
00475   // True if the find attribute has been set to something other than NULL.
00476   bool hasFind() const;
00477 
00478   // Return the attached find attribute for the expr.  Note that this
00479   // must be called repeatedly to get the root of the union-find tree.
00480   // It may also return a Null theorem if the attribute is not set.
00481   // Return by value, since a reference to the attribute may become
00482   // invalid at any point.
00483   Theorem getFind() const;
00484 
00485   // Return the notify list
00486   NotifyList* getNotify() const;
00487 
00488   //! Get the type.  Recursively compute if necessary
00489   const Type getType() const;
00490   //! Look up the current type. Do not recursively compute (i.e. may be NULL)
00491   const Type lookupType() const;
00492   //! Look up the cached TCC (may return Null)
00493   const Expr lookupTCC() const;
00494   //! Look up the cached subtyping predicate (may return Null)
00495   const Theorem lookupSubtypePred() const;
00496 
00497   /*! @brief Return true if there is a valid cached value for calling
00498       simplify on this Expr. */
00499   bool validSimpCache() const;
00500 
00501   // Get the cached Simplify of this Expr.
00502   const Theorem& getSimpCache() const;
00503 
00504   // Return true if valid type flag is set for Expr
00505   bool isValidType() const;
00506 
00507   // Return true if there is a valid flag for whether Expr is atomic
00508   bool validIsAtomicFlag() const;
00509 
00510   // Get the isAtomic flag
00511   bool getIsAtomicFlag() const;
00512 
00513   // Get the RewriteNormal flag
00514   bool isRewriteNormal() const;
00515 
00516   // Get the isFinite flag
00517   bool isFinite() const;
00518 
00519   // Get the WellFounded flag
00520   bool isWellFounded() const;
00521 
00522   // Get the ComputeTransClosure flag
00523   bool computeTransClosure() const;
00524 
00525   // Get the ImpliedLiteral flag
00526   bool isImpliedLiteral() const;
00527 
00528   // Get the UserAssumption flag
00529   bool isUserAssumption() const;
00530 
00531   // Get the IntAssumption flag
00532   bool isIntAssumption() const;
00533 
00534   // Get the Justified flag
00535   bool isJustified() const;
00536 
00537   // Get the Translated flag
00538   bool isTranslated() const;
00539 
00540   // Get the UserRegisteredAtom flag
00541   bool isUserRegisteredAtom() const;
00542 
00543   // Get the Selected flag
00544   bool isSelected() const;
00545 
00546   //! Check if the generic flag is set
00547   bool getFlag() const;
00548   //! Set the generic flag
00549   void setFlag() const;
00550   //! Clear the generic flag in all Exprs
00551   void clearFlags() const;
00552 
00553   // Printing functions
00554 
00555   //! Print the expression to a string
00556   std::string toString() const;
00557   //! Print the expression to a string using the given output language
00558   std::string toString(InputLanguage lang) const;
00559   //! Print the expression in the specified format
00560   void print(InputLanguage lang, bool dagify = true) const;
00561 
00562   //! Print the expression as AST (lisp-like format)
00563   void print() const { print(AST_LANG); }
00564   //! Print the expression as AST without dagifying
00565   void printnodag() const;
00566 
00567   //! Pretty-print the expression
00568   void pprint() const;
00569   //! Pretty-print without dagifying
00570   void pprintnodag() const;
00571 
00572   //! Print a leaf node
00573   /*@ The top node is pretty-printed if it is a basic leaf type;
00574    * otherwise, just the kind is printed.  Should only be called on expressions
00575    * with no children. */
00576   ExprStream& print(ExprStream& os) const;
00577   //! Print the top node and then recurse through the children */
00578   /*@ The top node is printed as an AST with all the information, including
00579    * "hidden" Exprs that are part of the ExprValue */
00580   ExprStream& printAST(ExprStream& os) const;
00581   //! Set initial indentation to n.
00582   /*! The indentation will be reset to default unless the second
00583     argument is true.
00584     \return reference to itself, so one can write `os << e.indent(5)'
00585   */
00586   Expr& indent(int n, bool permanent = false);
00587 
00588   /////////////////////////////////////////////////////////////////////////////
00589   // Other Public methods                                                    //
00590   /////////////////////////////////////////////////////////////////////////////
00591 
00592   // Attributes
00593 
00594   //! Set the find attribute to e
00595   void setFind(const Theorem& e) const;
00596 
00597   //! Add (e,i) to the notify list of this expression
00598   void addToNotify(Theory* i, const Expr& e) const;
00599 
00600   //! Set the cached type
00601   void setType(const Type& t) const;
00602   //! Set the cached TCC
00603   void setTCC(const Expr& tcc) const;
00604   //! Set the cached subtyping predicate
00605   void setSubtypePred(const Theorem& pred) const;
00606 
00607   // Cache the result of a call to Simplify on this Expr
00608   void setSimpCache(const Theorem& e) const;
00609 
00610   // Set the valid type flag for this Expr
00611   void setValidType() const;
00612 
00613   // Set the isAtomicFlag for this Expr
00614   void setIsAtomicFlag(bool value) const;
00615 
00616   // Set or clear the RewriteNormal flag
00617   void setRewriteNormal() const;
00618   void clearRewriteNormal() const;
00619 
00620   // Set the isFinite flag
00621   void setFinite() const;
00622 
00623   // Set the WellFounded flag
00624   void setWellFounded() const;
00625 
00626   // Set the ComputeTransClosure flag
00627   void setComputeTransClosure() const;
00628 
00629   // Set the impliedLiteral flag for this Expr
00630   void setImpliedLiteral() const;
00631 
00632   // Set the user assumption flag for this Expr
00633   void setUserAssumption(int scope = -1) const;
00634 
00635   // Set the internal assumption flag for this Expr
00636   void setIntAssumption() const;
00637 
00638   // Set the justified flag for this Expr
00639   void setJustified() const;
00640 
00641   //! Set the translated flag for this Expr
00642   void setTranslated(int scope = -1) const;
00643 
00644   //! Set the UserRegisteredAtom flag for this Expr
00645   void setUserRegisteredAtom() const;
00646 
00647   //! Set the Selected flag for this Expr
00648   void setSelected() const;
00649 
00650   //! Check if the current Expr (*this) is a subexpression of e
00651   bool subExprOf(const Expr& e) const;
00652   // Returns the maximum number of Boolean expressions on a path from
00653   // this to a leaf, including this.
00654   inline int getHeight() const;
00655 
00656   // Returns the index of the highest kid.
00657   inline int getHighestKid() const;
00658 
00659   // Gets/sets an expression that this expression was simplified from
00660   // (see newRWTheorem). This is the equivalent of SVC's Sigx.
00661   inline bool hasSimpFrom() const;
00662   inline const Expr& getSimpFrom() const;
00663   inline void setSimpFrom(const Expr& simpFrom);
00664 
00665   // Attributes for uninterpreted function symbols.
00666   bool hasSig() const;
00667   bool hasRep() const;
00668   const Theorem& getSig() const;
00669   const Theorem& getRep() const;
00670   void setSig(const Theorem& e) const;
00671   void setRep(const Theorem& e) const;
00672 
00673   /////////////////////////////////////////////////////////////////////////////
00674   // Friend methods                                                          //
00675   /////////////////////////////////////////////////////////////////////////////
00676 
00677   friend std::ostream& operator<<(std::ostream& os, const Expr& e);
00678 
00679   // The master method which defines some fixed total ordering on all
00680   // Exprs.  If e1 < e2, e1==e2, and e1 > e2, it returns -1, 0, 1
00681   // respectively.  A Null expr is always "smaller" than any other
00682   // expr, but is equal to itself.
00683   friend int compare(const Expr& e1, const Expr& e2);
00684 
00685   friend bool operator==(const Expr& e1, const Expr& e2);
00686   friend bool operator!=(const Expr& e1, const Expr& e2);
00687 
00688   friend bool operator<(const Expr& e1, const Expr& e2);
00689   friend bool operator<=(const Expr& e1, const Expr& e2);
00690   friend bool operator>(const Expr& e1, const Expr& e2);
00691   friend bool operator>=(const Expr& e1, const Expr& e2);
00692 
00693   /*!@}*/ // end of group Expr
00694 
00695 }; // end of class Expr
00696 
00697 } // end of namespace CVCL
00698 
00699 // Include expr_value.h here.  We cannot include it earlier, since it
00700 // needs the definition of class Expr.  See comments in expr_value.h.
00701 #ifndef DOXYGEN
00702 #include "expr_op.h"
00703 #include "expr_manager.h"
00704 #endif
00705 namespace CVCL {
00706 
00707 inline Expr::Expr(ExprValue* expr) : d_expr(expr) { d_expr->incRefcount(); }
00708 
00709 inline Expr::Expr(const Expr& e) : d_expr(e.d_expr) {
00710   if (d_expr != NULL) d_expr->incRefcount();
00711 }
00712 
00713 inline Expr& Expr::operator=(const Expr& e) {
00714   if(&e == this) return *this; // Self-assignment
00715   if(d_expr != NULL) {
00716     d_expr->decRefcount();
00717   }
00718   d_expr = e.d_expr;
00719   if(d_expr != NULL)
00720     d_expr->incRefcount();
00721   return *this;
00722 }
00723 
00724 inline Expr::Expr(const Op& op, const Expr& child) {
00725   std::vector<Expr> kids;
00726   kids.push_back(child);
00727   ExprManager* em = child.getEM();
00728   if (op.getExpr().isNull()) {
00729     ExprNode ev(em, op.getKind(), kids);
00730     d_expr = em->newExprValue(&ev);
00731   } else {
00732     ExprApply ev(em, op, kids);
00733     d_expr = em->newExprValue(&ev);
00734   }
00735   d_expr->incRefcount();
00736 }
00737  
00738 inline Expr::Expr(const Op& op, const Expr& child0, const Expr& child1) {
00739   std::vector<Expr> kids;
00740   kids.push_back(child0);
00741   kids.push_back(child1);
00742   ExprManager* em = child0.getEM();
00743   if (op.getExpr().isNull()) {
00744     ExprNode ev(em, op.getKind(), kids);
00745     d_expr = em->newExprValue(&ev);
00746   } else {
00747     ExprApply ev(em, op, kids);
00748     d_expr = em->newExprValue(&ev);
00749   }
00750   d_expr->incRefcount();
00751 }
00752 
00753 inline Expr::Expr(const Op& op, const Expr& child0, const Expr& child1,
00754                   const Expr& child2) {
00755   ExprManager* em = child0.getEM();
00756   std::vector<Expr> kids;
00757   kids.push_back(child0);
00758   kids.push_back(child1);
00759   kids.push_back(child2);
00760   if (op.getExpr().isNull()) {
00761     ExprNode ev(em, op.getKind(), kids);
00762     d_expr = em->newExprValue(&ev);
00763   } else {
00764     ExprApply ev(em, op, kids);
00765     d_expr = em->newExprValue(&ev);
00766   }
00767   d_expr->incRefcount();
00768 }
00769 
00770 inline Expr::Expr(const Op& op, const Expr& child0, const Expr& child1,
00771                   const Expr& child2, const Expr& child3) {
00772   ExprManager* em = child0.getEM();
00773   std::vector<Expr> kids;
00774   kids.push_back(child0);
00775   kids.push_back(child1);
00776   kids.push_back(child2);
00777   kids.push_back(child3);
00778   if (op.getExpr().isNull()) {
00779     ExprNode ev(em, op.getKind(), kids);
00780     d_expr = em->newExprValue(&ev);
00781   } else {
00782     ExprApply ev(em, op, kids);
00783     d_expr = em->newExprValue(&ev);
00784   }
00785   d_expr->incRefcount();
00786 }
00787 
00788 inline Expr::Expr(const Op& op, const std::vector<Expr>& children,
00789                   ExprManager* em) {
00790   if (em == NULL) {
00791     if (!op.getExpr().isNull()) em = op.getExpr().getEM();
00792     else {
00793       DebugAssert(children.size() > 0,
00794                   "Expr::Expr(Op, children): op's EM is NULL and "
00795                   "no children given");
00796       em = children[0].getEM();
00797     }
00798   }
00799   if (op.getExpr().isNull()) {
00800     ExprNode ev(em, op.getKind(), children);
00801     d_expr = em->newExprValue(&ev);
00802   } else {
00803     ExprApply ev(em, op, children);
00804     d_expr = em->newExprValue(&ev);
00805   }
00806   d_expr->incRefcount();
00807 }
00808 
00809 inline Expr Expr::eqExpr(const Expr& right) const {
00810   return Expr(EQ, *this, right);
00811 }
00812 
00813 inline Expr Expr::notExpr() const {
00814   return Expr(NOT, *this);
00815 }
00816 
00817 inline Expr Expr::negate() const {
00818   return isNot() ? (*this)[0] : this->notExpr();
00819 }
00820 
00821 inline Expr Expr::andExpr(const Expr& right) const {
00822   return Expr(AND, *this, right);
00823 }
00824 
00825 inline Expr andExpr(const std::vector <Expr>& children) {
00826   DebugAssert(children.size()>0 && !children[0].isNull(),
00827               "Expr::andExpr(kids)");
00828   return Expr(AND, children);
00829 }
00830 
00831 inline Expr Expr::orExpr(const Expr& right) const {
00832   return Expr(OR, *this, right);
00833 }
00834 
00835 inline Expr orExpr(const std::vector <Expr>& children) {
00836   DebugAssert(children.size()>0 && !children[0].isNull(),
00837               "Expr::andExpr(kids)");
00838   return Expr(OR, children);
00839 }
00840 
00841 inline Expr Expr::iteExpr(const Expr& thenpart, const Expr& elsepart) const {
00842   return Expr(ITE, *this, thenpart, elsepart);
00843 }
00844 
00845 inline Expr Expr::iffExpr(const Expr& right) const {
00846   return Expr(IFF, *this, right);
00847 }
00848 
00849 inline Expr Expr::impExpr(const Expr& right) const {
00850   return Expr(IMPLIES, *this, right);
00851 }
00852 
00853 inline Expr Expr::skolemExpr(int i) const {
00854   return getEM()->newSkolemExpr(*this, i);
00855 }
00856 
00857 inline Expr Expr::rebuild(ExprManager* em) const {
00858   return em->rebuild(*this);
00859 }
00860 
00861 inline Expr::~Expr() {
00862   if(d_expr != NULL && !d_expr->d_em->d_disableGC) {
00863     d_expr->decRefcount();
00864   }
00865 }
00866 
00867 inline size_t Expr::hash(const Expr& e) { return e.getEM()->hash(e); }
00868 
00869 /////////////////////////////////////////////////////////////////////////////
00870 // Read-only (const) methods                                               //
00871 /////////////////////////////////////////////////////////////////////////////
00872 
00873 inline size_t Expr::hash() const { return getEM()->hash(*this); }
00874 
00875 inline const ExprValue* Expr::getExprValue() const
00876   { return d_expr->getExprValue(); }
00877 
00878 // Core Expression Testers
00879 
00880 inline bool Expr::isVar() const { return d_expr->isVar(); }
00881 inline bool Expr::isString() const { return d_expr->isString(); }
00882 inline bool Expr::isClosure() const { return d_expr->isClosure(); }
00883 inline bool Expr::isQuantifier() const {
00884   return (isClosure() && (getKind() == FORALL || getKind() == EXISTS));
00885 }
00886 inline bool Expr::isLambda() const {
00887   return (isClosure() && getKind() == LAMBDA);
00888 }
00889 inline bool Expr::isApply() const 
00890 { DebugAssert((getKind() != APPLY || d_expr->isApply()) &&
00891               (!d_expr->isApply() || getKind() == APPLY), "APPLY mismatch");
00892   return d_expr->isApply(); }
00893 inline bool Expr::isSymbol() const { return d_expr->isSymbol(); }
00894 inline bool Expr::isType() const { return getEM()->isTypeKind(getOpKind()); }
00895 inline bool Expr::isTerm() const { return !getType().isBool(); }
00896 inline bool Expr::isBoolConnective() const {
00897   if (!getType().isBool()) return false;
00898   switch (getKind()) {
00899     case NOT: case AND: case OR: case IMPLIES: case IFF: case XOR: case ITE:
00900       return true; }
00901   return false;
00902 }
00903 
00904 inline int Expr::getHeight() const { return d_expr->getHeight(); }
00905 inline int Expr::getHighestKid() const { return d_expr->getHighestKid(); }
00906 
00907 inline bool Expr::hasSimpFrom() const
00908   { return !d_expr->getSimpFrom().isNull(); }
00909 inline const Expr& Expr::getSimpFrom() const
00910   { return hasSimpFrom() ? d_expr->getSimpFrom() : *this; }
00911 inline void Expr::setSimpFrom(const Expr& simpFrom)
00912   { d_expr->setSimpFrom(simpFrom); }
00913 
00914 // Leaf accessors
00915 
00916 inline const std::string& Expr::getName() const {
00917   DebugAssert(!isNull(), "Expr::getName() on Null expr");
00918   return d_expr->getName();
00919 }
00920 
00921 inline const std::string& Expr::getString() const {
00922    DebugAssert(isString(),
00923         "CVCL::Expr::getString(): not a string Expr:\n  "
00924         + toString(AST_LANG));
00925    return d_expr->getString();
00926 }
00927 
00928 inline const std::vector<Expr>& Expr::getVars() const {
00929    DebugAssert(isClosure(),
00930         "CVCL::Expr::getVars(): not a closure Expr:\n  "
00931         + toString(AST_LANG));
00932    return d_expr->getVars();
00933 }
00934 
00935 inline const Expr& Expr::getBody() const {
00936    DebugAssert(isClosure(),
00937         "CVCL::Expr::getBody(): not a closure Expr:\n  "
00938         + toString(AST_LANG));
00939    return d_expr->getBody();
00940 }
00941 
00942 inline const Expr& Expr::getExistential() const {
00943   DebugAssert(isSkolem(),
00944               "CVCL::Expr::getExistential() not a skolem variable");
00945   return d_expr->getExistential();
00946 }
00947 inline int Expr::getBoundIndex() const {
00948   DebugAssert(isSkolem(),
00949               "CVCL::Expr::getBoundIndex() not a skolem variable");
00950   return d_expr->getBoundIndex();
00951 }
00952 
00953 
00954 inline const Rational& Expr::getRational() const {
00955   DebugAssert(isRational(),
00956         "CVCL::Expr::getRational(): not a rational Expr:\n  "
00957         + toString(AST_LANG));
00958    return d_expr->getRational();
00959 }
00960 
00961 inline const std::string& Expr::getUid() const {
00962    DebugAssert(getKind() == BOUND_VAR,
00963         "CVCL::Expr::getUid(): not a BOUND_VAR Expr:\n  "
00964         + toString(AST_LANG));
00965    return d_expr->getUid();
00966 }
00967 
00968 inline ExprManager* Expr::getEM() const {
00969   DebugAssert(d_expr != NULL,
00970               "CVCL::Expr:getEM: on Null Expr (not initialized)");
00971   return d_expr->d_em;
00972 }
00973 
00974 inline const std::vector<Expr>& Expr::getKids() const {
00975   DebugAssert(d_expr != NULL, "Expr::getKids on Null Expr");
00976   if(isNull()) return getEM()->getEmptyVector();
00977   else return d_expr->getKids();
00978 }
00979 
00980 inline int Expr::getKind() const {
00981    if(d_expr == NULL) return NULL_KIND; // FIXME: invent a better Null kind
00982    return d_expr->d_kind;
00983  }
00984 
00985 inline ExprIndex Expr::getIndex() const { return d_expr->d_index; }
00986 
00987 inline bool Expr::hasLastIndex() const
00988 { return d_expr->d_em->lastIndex() == getIndex(); }
00989 
00990 inline Op Expr::mkOp() const {
00991   DebugAssert(!isNull(), "Expr::mkOp() on Null expr");
00992   return Op(*this);
00993 }
00994 
00995 inline Op Expr::getOp() const {
00996   DebugAssert(!isNull(), "Expr::getOp() on Null expr");
00997   if (isApply()) return d_expr->getOp();
00998   DebugAssert(arity() > 0,
00999               "Expr::getOp() called on non-apply expr with no children");
01000   return Op(getKind());
01001 }
01002 
01003 inline Expr Expr::getOpExpr() const {
01004   DebugAssert(isApply(), "getOpExpr() called on non-apply");
01005   return getOp().getExpr();
01006 }
01007 
01008 inline int Expr::getOpKind() const {
01009   if (!isApply()) return getKind();
01010   return getOp().getExpr().getKind();
01011 }
01012 
01013 inline int Expr::arity() const {
01014   if(isNull()) return 0;
01015   else return d_expr->arity();
01016 }
01017 
01018 inline const Expr& Expr::operator[](int i) const {
01019   DebugAssert(i < arity(), "out of bounds access");
01020   return (d_expr->getKids())[i];
01021 }
01022 
01023 inline bool Expr::isNull() const {
01024   return (d_expr == NULL) || (d_expr->d_kind == NULL_KIND);
01025 }
01026 
01027 inline size_t Expr::getMMIndex() const {
01028   DebugAssert(!isNull(), "Expr::getMMIndex()");
01029   return d_expr->getMMIndex();
01030 }
01031 
01032 inline bool Expr::hasFind() const {
01033   DebugAssert(!isNull(), "hasFind called on NULL Expr");
01034   return (d_expr->d_find && !(d_expr->d_find->get().isNull()));
01035 }
01036 
01037 inline Theorem Expr::getFind() const {
01038   DebugAssert(hasFind(), "Should only be called if find is valid");
01039   return d_expr->d_find->get();
01040 }
01041 
01042 inline NotifyList* Expr::getNotify() const {
01043   if(isNull()) return NULL;
01044   else return d_expr->d_notifyList;
01045 }
01046 
01047 inline const Type Expr::getType() const {
01048   if (isNull()) return s_null;
01049   if(d_expr->d_type.isNull()) getEM()->computeType(*this);
01050   return d_expr->d_type;
01051 }
01052 
01053 inline const Type Expr::lookupType() const {
01054   if (isNull()) return s_null;
01055   return d_expr->d_type;
01056 }
01057 
01058 inline const Expr Expr::lookupTCC() const {
01059   if(isNull()) return s_null;
01060   else return d_expr->d_tcc;
01061 }
01062 
01063 inline const Theorem Expr::lookupSubtypePred() const {
01064   if(isNull()) return Theorem();
01065   else return d_expr->d_subtypePred;
01066 }
01067 
01068 inline bool Expr::validSimpCache() const {
01069   return d_expr->d_simpCacheTag == getEM()->getSimpCacheTag();
01070 }
01071 
01072 inline const Theorem& Expr::getSimpCache() const {
01073   return d_expr->d_simpCache;
01074 }
01075 
01076 inline bool Expr::isValidType() const {
01077   return d_expr->d_dynamicFlags.get(VALID_TYPE);
01078 }
01079 
01080 inline bool Expr::validIsAtomicFlag() const {
01081   return d_expr->d_dynamicFlags.get(VALID_IS_ATOMIC);
01082 }
01083 
01084 inline bool Expr::getIsAtomicFlag() const {
01085   return d_expr->d_dynamicFlags.get(IS_ATOMIC);
01086 }
01087 
01088 inline bool Expr::isRewriteNormal() const {
01089   return d_expr->d_dynamicFlags.get(REWRITE_NORMAL);
01090 }
01091 
01092 inline bool Expr::isFinite() const {
01093   return d_expr->d_dynamicFlags.get(IS_FINITE);
01094 }
01095 
01096 inline bool Expr::isWellFounded() const {
01097   return d_expr->d_dynamicFlags.get(WELL_FOUNDED);
01098 }
01099 
01100 inline bool Expr::computeTransClosure() const {
01101   return d_expr->d_dynamicFlags.get(COMPUTE_TRANS_CLOSURE);
01102 }
01103 
01104 inline bool Expr::isImpliedLiteral() const {
01105   return d_expr->d_dynamicFlags.get(IMPLIED_LITERAL);
01106 }
01107 
01108 inline bool Expr::isUserAssumption() const {
01109   return d_expr->d_dynamicFlags.get(IS_USER_ASSUMPTION);
01110 }
01111 
01112 inline bool Expr::isIntAssumption() const {
01113   return d_expr->d_dynamicFlags.get(IS_INT_ASSUMPTION);
01114 }
01115 
01116 inline bool Expr::isJustified() const {
01117   return d_expr->d_dynamicFlags.get(IS_JUSTIFIED);
01118 }
01119 
01120 inline bool Expr::isTranslated() const {
01121   return d_expr->d_dynamicFlags.get(IS_TRANSLATED);
01122 }
01123 
01124 inline bool Expr::isUserRegisteredAtom() const {
01125   return d_expr->d_dynamicFlags.get(IS_USER_REGISTERED_ATOM);
01126 }
01127 
01128 inline bool Expr::isSelected() const {
01129   return d_expr->d_dynamicFlags.get(IS_SELECTED);
01130 }
01131 
01132 inline bool Expr::getFlag() const {
01133   DebugAssert(!isNull(), "Expr::getFlag() on Null Expr");
01134   return (d_expr->d_flag == getEM()->getFlag());
01135 }
01136 
01137 inline void Expr::setFlag() const {
01138   DebugAssert(!isNull(), "Expr::setFlag() on Null Expr");
01139   d_expr->d_flag = getEM()->getFlag();
01140 }
01141 
01142 inline void Expr::clearFlags() const {
01143   DebugAssert(!isNull(), "Expr::clearFlags() on Null Expr");
01144   getEM()->clearFlags();
01145 }
01146 
01147 inline void Expr::setFind(const Theorem& e) const {
01148   DebugAssert(!isNull(), "Expr::setFind() on Null expr");
01149   DebugAssert(e.getLHS() == *this, "bad call to setFind");
01150   if (d_expr->d_find) d_expr->d_find->set(e);
01151   else {
01152     CDO<Theorem>* tmp = new CDO<Theorem>(getEM()->getCurrentContext(), e);
01153     d_expr->d_find = tmp;
01154     IF_DEBUG(tmp->setName("CDO[Expr.find]"));
01155   }
01156 }
01157 
01158 inline void Expr::setType(const Type& t) const {
01159   DebugAssert(!isNull(), "Expr::setType() on Null expr");
01160   d_expr->d_type = t;
01161 }
01162 
01163 inline void Expr::setTCC(const Expr& tcc) const {
01164   DebugAssert(!isNull(), "Expr::setTCC() on Null expr");
01165   d_expr->d_tcc = tcc;
01166 }
01167 
01168 inline void Expr::setSubtypePred(const Theorem& pred) const {
01169   DebugAssert(!isNull(), "Expr::setSubtypePred() on Null expr");
01170   d_expr->d_subtypePred = pred;
01171 }
01172 
01173 inline void Expr::setSimpCache(const Theorem& e) const {
01174   DebugAssert(!isNull(), "Expr::setSimpCache() on Null expr");
01175   d_expr->d_simpCache = e;
01176   d_expr->d_simpCacheTag = getEM()->getSimpCacheTag();
01177 }
01178 
01179 inline void Expr::setValidType() const {
01180   DebugAssert(!isNull(), "Expr::setValidType() on Null expr");
01181   d_expr->d_dynamicFlags.set(VALID_TYPE, 0);
01182 }
01183 
01184 inline void Expr::setIsAtomicFlag(bool value) const {
01185   DebugAssert(!isNull(), "Expr::setIsAtomicFlag() on Null expr");
01186   d_expr->d_dynamicFlags.set(VALID_IS_ATOMIC, 0);
01187   if (value) d_expr->d_dynamicFlags.set(IS_ATOMIC, 0);
01188   else d_expr->d_dynamicFlags.clear(IS_ATOMIC, 0);
01189 }
01190 
01191 inline void Expr::setRewriteNormal() const {
01192   DebugAssert(!isNull(), "Expr::setRewriteNormal() on Null expr");
01193   TRACE("setRewriteNormal", "setRewriteNormal(", *this, ")");
01194   d_expr->d_dynamicFlags.set(REWRITE_NORMAL, 0);
01195 }
01196 
01197 inline void Expr::setFinite() const {
01198   DebugAssert(!isNull(), "Expr::setFinite() on Null expr");
01199   d_expr->d_dynamicFlags.set(IS_FINITE, 0);
01200 }
01201 
01202 inline void Expr::setWellFounded() const {
01203   DebugAssert(!isNull(), "Expr::setWellFounded() on Null expr");
01204   d_expr->d_dynamicFlags.set(WELL_FOUNDED, 0);
01205 }
01206 
01207 inline void Expr::setComputeTransClosure() const {
01208   DebugAssert(!isNull(), "Expr::setComputeTransClosure() on Null expr");
01209   d_expr->d_dynamicFlags.set(COMPUTE_TRANS_CLOSURE, 0);
01210 }
01211 
01212 inline void Expr::setImpliedLiteral() const {
01213   DebugAssert(!isNull(), "Expr::setImpliedLiteral() on Null expr");
01214   d_expr->d_dynamicFlags.set(IMPLIED_LITERAL);
01215 }
01216 
01217 inline void Expr::setUserAssumption(int scope) const {
01218   DebugAssert(!isNull(), "Expr::setUserAssumption() on Null expr");
01219   d_expr->d_dynamicFlags.set(IS_USER_ASSUMPTION, scope);
01220 }
01221 
01222 inline void Expr::setIntAssumption() const {
01223   DebugAssert(!isNull(), "Expr::setIntAssumption() on Null expr");
01224   d_expr->d_dynamicFlags.set(IS_INT_ASSUMPTION);
01225 }
01226 
01227 inline void Expr::setJustified() const {
01228   DebugAssert(!isNull(), "Expr::setJustified() on Null expr");
01229   d_expr->d_dynamicFlags.set(IS_JUSTIFIED);
01230 }
01231 
01232 inline void Expr::setTranslated(int scope) const {
01233   DebugAssert(!isNull(), "Expr::setTranslated() on Null expr");
01234   d_expr->d_dynamicFlags.set(IS_TRANSLATED, scope);
01235 }
01236 
01237 inline void Expr::setUserRegisteredAtom() const {
01238   DebugAssert(!isNull(), "Expr::setUserRegisteredAtom() on Null expr");
01239   d_expr->d_dynamicFlags.set(IS_USER_REGISTERED_ATOM);
01240 }
01241 
01242 inline void Expr::setSelected() const {
01243   DebugAssert(!isNull(), "Expr::setSelected() on Null expr");
01244   d_expr->d_dynamicFlags.set(IS_SELECTED);
01245 }
01246 
01247 inline void Expr::clearRewriteNormal() const {
01248   DebugAssert(!isNull(), "Expr::clearRewriteNormal() on Null expr");
01249   d_expr->d_dynamicFlags.clear(REWRITE_NORMAL, 0);
01250 }
01251 
01252 inline bool Expr::hasSig() const {
01253   return (!isNull()
01254           && d_expr->getSig() != NULL 
01255           && !(d_expr->getSig()->get().isNull()));
01256 }
01257 
01258 inline bool Expr::hasRep() const {
01259   return (!isNull()
01260           && d_expr->getRep() != NULL 
01261           && !(d_expr->getRep()->get().isNull()));
01262 }
01263 
01264 inline const Theorem& Expr::getSig() const {
01265   static Theorem nullThm;   
01266   DebugAssert(!isNull(), "Expr::getSig() on Null expr");
01267   if(d_expr->getSig() != NULL)
01268     return d_expr->getSig()->get();
01269   else
01270     return nullThm;
01271 }
01272 
01273 inline const Theorem& Expr::getRep() const {
01274   static Theorem nullThm;
01275   DebugAssert(!isNull(), "Expr::getRep() on Null expr");
01276   if(d_expr->getRep() != NULL)
01277     return d_expr->getRep()->get();
01278   else
01279     return nullThm;
01280 }
01281 
01282 inline void Expr::setSig(const Theorem& e) const {
01283   DebugAssert(!isNull(), "Expr::setSig() on Null expr");
01284   CDO<Theorem>* sig = d_expr->getSig();
01285   if(sig != NULL) sig->set(e);
01286   else {
01287     CDO<Theorem>* tmp = new CDO<Theorem>(getEM()->getCurrentContext(), e);
01288     d_expr->setSig(tmp);
01289     IF_DEBUG(tmp->setName("CDO[Expr.sig] in "+toString()));
01290   }
01291 }
01292 
01293 inline void Expr::setRep(const Theorem& e) const {
01294   DebugAssert(!isNull(), "Expr::setRep() on Null expr");
01295   CDO<Theorem>* rep = d_expr->getRep();
01296   if(rep != NULL) rep->set(e);
01297   else {
01298     CDO<Theorem>* tmp = new CDO<Theorem>(getEM()->getCurrentContext(), e);
01299     d_expr->setRep(tmp);
01300     IF_DEBUG(tmp->setName("CDO[Expr.rep] in "+toString()));
01301   }
01302 }
01303  
01304 inline bool operator==(const Expr& e1, const Expr& e2) {
01305   // Comparing pointers (equal expressions are always shared)
01306   return e1.d_expr == e2.d_expr;
01307 }
01308 
01309 inline bool operator!=(const Expr& e1, const Expr& e2)
01310   { return !(e1 == e2); }
01311 
01312 // compare() is defined in expr.cpp
01313 
01314 inline bool operator<(const Expr& e1, const Expr& e2)
01315   { return compare(e1,e2) < 0; }
01316 inline bool operator<=(const Expr& e1, const Expr& e2)
01317   { return compare(e1,e2) <= 0; }
01318 inline bool operator>(const Expr& e1, const Expr& e2)
01319   { return compare(e1,e2) > 0; }
01320 inline bool operator>=(const Expr& e1, const Expr& e2)
01321   { return compare(e1,e2) >= 0; }
01322 
01323 } // end of namespace CVCL
01324 
01325 #endif

Generated on Thu Apr 13 16:57:31 2006 for CVC Lite by  doxygen 1.4.4