expr_manager.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file expr_manager.h
00004  * \brief Expression manager API
00005  * 
00006  * Author: Sergey Berezin
00007  * 
00008  * Created: Wed Dec  4 14:20:56 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 // Must be before #ifndef, since expr.h also includes this file (see
00031 // comments in expr_value.h)
00032 #ifndef _CVC_lite__expr_h_
00033 #include "expr.h"
00034 #endif
00035 
00036 #ifndef _CVC_lite__include__expr_manager_h_
00037 #define _CVC_lite__include__expr_manager_h_
00038 
00039 #include "expr_map.h"
00040 
00041 namespace CVCL {
00042   // Command line flags
00043   class CLFlags;
00044   class PrettyPrinter;
00045   class MemoryManager;
00046   class ExprManagerNotifyObj;
00047 
00048 ///////////////////////////////////////////////////////////////////////////////
00049 //! Expression Manager
00050 /*!
00051   Class: ExprManager
00052   
00053   Author: Sergey Berezin
00054  
00055   Created: Wed Dec  4 14:26:35 2002
00056 
00057   Description: Global state of the Expr package for a particular
00058     instance of CVC Lite.  Each instance of the CVC Lite library has
00059     its own expression manager, for thread-safety.
00060 */
00061 ///////////////////////////////////////////////////////////////////////////////
00062 
00063   class ExprManager {
00064     friend class Expr;
00065     friend class ExprValue;
00066     friend class Op; // It wants to call rebuildExpr
00067     friend class HashEV; // Our own private class
00068     friend class Type;
00069 
00070     ContextManager* d_cm; //!< For backtracking attributes
00071     ExprManagerNotifyObj* d_notifyObj; //!< Notification on pop()
00072     ExprIndex d_index; //!< Index counter for Expr compare()
00073     unsigned d_flagCounter; //!< Counter for a generic Expr flag
00074 
00075     //! The database of registered kinds
00076     std::hash_map<int, std::string> d_kindMap;
00077     //! The set of kinds representing a type
00078     std::hash_set<int> d_typeKinds;
00079     //! Private class for hashing strings
00080     class HashString {
00081       std::hash<char*> h;
00082     public:
00083       size_t operator()(const std::string& s) const {
00084         return h(const_cast<char*>(s.c_str()));
00085       }
00086     };
00087     //! The reverse map of names to kinds
00088     std::hash_map<std::string, int, HashString> d_kindMapByName;
00089     /*! @brief The registered pretty-printer, a connector to
00090       theory-specific pretty-printers */
00091     PrettyPrinter *d_prettyPrinter;
00092 
00093     size_t hash(const ExprValue* ev) const;
00094 
00095     // Printing and other options 
00096 
00097     /*! @brief Print upto the given depth, replace the rest with
00098      "...".  -1==unlimited depth. */
00099     const int* d_printDepth;
00100     //! Whether to print with indentation
00101     const bool* d_withIndentation;
00102     //! Permanent indentation
00103     int d_indent;
00104     //! Transient indentation
00105     /*! Normally is the same as d_indent, but may temporarily be
00106       different for printing one single Expr */
00107     int d_indentTransient;
00108     //! Suggested line width for printing with indentation
00109     const int* d_lineWidth;
00110     //! Input language (printing)
00111     const std::string* d_inputLang;
00112     //! Output language (printing)
00113     const std::string* d_outputLang;
00114     //! Whether to print Expr's as DAGs
00115     const bool* d_dagPrinting;
00116     //! Which memory manager to use (copy the flag value and keep it the same)
00117     const std::string d_mmFlag;
00118 
00119     //! Private classe for d_exprSet
00120     class HashEV {
00121       ExprManager* d_em;
00122     public:
00123       HashEV(ExprManager* em): d_em(em) { }
00124       size_t operator()(ExprValue* ev) const { return d_em->hash(ev); }
00125     };
00126     //! Private class for d_exprSet
00127     class EqEV {
00128     public:
00129       bool operator()(const ExprValue* ev1, const ExprValue* ev2) const;
00130     };
00131 
00132     //! Hash set type for uniquifying expressions
00133     typedef std::hash_set<ExprValue*, HashEV, EqEV> ExprValueSet;
00134     //! Hash set for uniquifying expressions
00135     ExprValueSet d_exprSet;
00136     //! Array of memory managers for subclasses of ExprValue
00137     std::vector<MemoryManager*> d_mm;
00138 
00139     //! A hash function for hashing pointers
00140     std::hash<void*> d_pointerHash;
00141     
00142     //! Expr constants cached for fast access
00143     Expr d_bool;
00144     Expr d_false;
00145     Expr d_true;
00146     //! Empty vector of Expr to return by reference as empty vector of children
00147     std::vector<Expr> d_emptyVec;
00148     //! Null Expr to return by reference, for efficiency
00149     Expr d_nullExpr;
00150 
00151     void installExprValue(ExprValue* ev);
00152 
00153     //! Current value of the simplifier cache tag
00154     /*! The cached values of calls to Simplify are valid as long as
00155       their cache tag matches this tag.  Caches can then be
00156       invalidated by incrementing this tag. */
00157     unsigned d_simpCacheTagCurrent;
00158 
00159     //! Disable garbage collection
00160     /*! This flag disables the garbage collection.  Normally, it's set
00161       in the destructor, so that we can delete all remaining
00162       expressions without GC getting in the way. */
00163     bool d_disableGC;
00164     //! Postpone deleting garbage-collected expressions.
00165     /*! Useful during manipulation of context, especially at the time
00166      * of backtracking, since we may have objects with circular
00167      * dependencies (like find pointers).
00168      *
00169      * The postponed expressions will be deleted the next time the
00170      * garbage collector is called after this flag is cleared.
00171      */
00172     bool d_postponeGC;
00173     //! Vector of postponed garbage-collected expressions
00174     std::vector<ExprValue*> d_postponed;
00175     //! Rebuild cache
00176     ExprHashMap<Expr> d_rebuildCache;
00177     IF_DEBUG(bool d_inRebuild);
00178 
00179   public:
00180     //! Abstract class for computing expr type
00181     class TypeComputer {
00182     public:
00183       TypeComputer() {}
00184       virtual ~TypeComputer() {}
00185       //! Compute the type of e
00186       virtual void computeType(const Expr& e) = 0;
00187       //! Check that e is a valid Type expr
00188       virtual void checkType(const Expr& e) = 0;
00189     };
00190   private:
00191     //! Instance of TypeComputer: must be registered
00192     TypeComputer* d_typeComputer;
00193 
00194     /////////////////////////////////////////////////////////////////////////
00195     /*! \defgroup EM_Priv Private methods
00196      * \ingroup ExprPkg
00197      * @{
00198      */
00199     /////////////////////////////////////////////////////////////////////////
00200 
00201     //! Cached recursive descent.  Must be called only during rebuild()
00202     Expr rebuildRec(const Expr& e);
00203 
00204     //! Return either an existing or a new ExprValue matching ev
00205     ExprValue* newExprValue(ExprValue* ev);
00206 
00207     //! Return the current Expr flag counter
00208     unsigned getFlag() { return d_flagCounter; }
00209     //! Increment and return the Expr flag counter (this clears all the flags)
00210     unsigned nextFlag() { return ++d_flagCounter; }
00211 
00212     //! Compute the type of the Expr
00213     void computeType(const Expr& e);
00214     //! Check well-formedness of a type Expr
00215     void checkType(const Expr& e);
00216 
00217   public:
00218     //! Constructor
00219     ExprManager(ContextManager* cm, const CLFlags& flags);
00220     //! Destructor
00221     ~ExprManager();
00222     //! Free up all memory and delete all the expressions.
00223     /*!
00224      * No more expressions can be created after this point, only
00225      * destructors ~Expr() can be called.
00226      *
00227      * This method is needed to dis-entangle the mutual dependency of
00228      * ExprManager and ContextManager, when destructors of ExprValue
00229      * (sub)classes need to delete backtracking objects, and deleting
00230      * the ContextManager requires destruction of some remaining Exprs.
00231      */
00232     void clear();
00233     //! Check if the ExprManager is still active (clear() was not called)
00234     bool isActive();
00235 
00236     //! Garbage collect the ExprValue pointer 
00237     /*! \ingroup EM_Priv */
00238     void gc(ExprValue* ev);
00239     //! Postpone deletion of garbage-collected expressions.
00240     /*! \sa resumeGC() */
00241     void postponeGC() { d_postponeGC = true; }
00242     //! Resume deletion of garbage-collected expressions.
00243     /*! \sa postponeGC() */
00244     void resumeGC();
00245 
00246     /*! @brief Rebuild the Expr with this ExprManager if it belongs to
00247       another ExprManager */
00248     Expr rebuild(const Expr& e);
00249 
00250     //! Return the next Expr index
00251     /*! It should be used only by ExprValue() constructor */
00252     ExprIndex nextIndex() { return d_index++; }
00253     ExprIndex lastIndex() { return d_index - 1; }
00254 
00255     //! Clears the generic Expr flag in all Exprs
00256     void clearFlags() { nextFlag(); }
00257 
00258     // Core leaf exprs
00259     //! BOOLEAN Expr
00260     const Expr& boolExpr() { return d_bool; }
00261     //! FALSE Expr
00262     const Expr& falseExpr() { return d_false; }
00263     //! TRUE Expr
00264     const Expr& trueExpr() { return d_true; }
00265     //! References to empty objects (used in ExprValue)
00266     const std::vector<Expr>& getEmptyVector() { return d_emptyVec; }
00267     //! References to empty objects (used in ExprValue)
00268     const Expr& getNullExpr() { return d_nullExpr; }
00269 
00270     // Expr constructors
00271 
00272     //! Return either an existing or a new Expr matching ev
00273     Expr newExpr(ExprValue* ev) { return Expr(newExprValue(ev)); }
00274 
00275     Expr newLeafExpr(const Op& op);
00276     Expr newStringExpr(const std::string &s);
00277     Expr newRatExpr(const Rational& r);
00278     Expr newSkolemExpr(const Expr& e, int i);
00279     Expr newVarExpr(const std::string &s);
00280     Expr newSymbolExpr(const std::string &s, int kind);
00281     Expr newBoundVarExpr(const std::string &name, const std::string& uid);
00282     Expr newBoundVarExpr(const std::string &name, const std::string& uid,
00283                          const Type& type);
00284     Expr newBoundVarExpr(const Type& type);
00285     Expr newClosureExpr(int kind, const std::vector<Expr>& vars,
00286                         const Expr& body);
00287 
00288     // Vector of children constructors (vector may be empty)
00289     Expr andExpr(const std::vector <Expr>& children)
00290      { return Expr(AND, children, this); }
00291     Expr orExpr(const std::vector <Expr>& children)
00292      { return Expr(OR, children, this); }
00293 
00294     // Public methods
00295 
00296     //! Hash function for a single Expr
00297     size_t hash(const Expr& e) const;
00298     //! Fetch our ContextManager
00299     ContextManager* getCM() const { return d_cm; }
00300     //! Get the current context from our ContextManager
00301     Context* getCurrentContext() const { return d_cm->getCurrentContext(); }
00302     //! Get current scope level
00303     int scopelevel() { return d_cm->scopeLevel(); }
00304 
00305     //! Return a MemoryManager for the given ExprValue type
00306     MemoryManager* getMM(size_t MMIndex) {
00307       DebugAssert(MMIndex < d_mm.size(), "ExprManager::getMM()");
00308       return d_mm[MMIndex];
00309     }
00310     //! Get the simplifier's cache tag
00311     unsigned getSimpCacheTag() const { return d_simpCacheTagCurrent; }
00312     //! Invalidate the simplifier's cache tag
00313     void invalidateSimpCache() { d_simpCacheTagCurrent++; }
00314 
00315     //! Register type computer
00316     void registerTypeComputer(TypeComputer* typeComputer)
00317       { d_typeComputer = typeComputer; }
00318 
00319     //! Get printing depth
00320     int printDepth() const { return *d_printDepth; }
00321     //! Whether to print with indentation
00322     bool withIndentation() const { return *d_withIndentation; }
00323     //! Suggested line width for printing with indentation
00324     int lineWidth() const { return *d_lineWidth; }
00325     //! Get initial indentation
00326     int indent() const { return d_indentTransient; }
00327     //! Set initial indentation.  Returns the previous permanent value.
00328     int indent(int n, bool permanent = false);
00329     //! Increment the current transient indentation by n
00330     /*! If the second argument is true, sets the result as permanent.
00331       \return previous permanent value. */
00332     int incIndent(int n, bool permanent = false);
00333     //! Set transient indentation to permanent
00334     void restoreIndent() { d_indentTransient = d_indent; }
00335     //! Get the input language for printing
00336     InputLanguage getInputLang() const;
00337     //! Get the output language for printing
00338     InputLanguage getOutputLang() const;
00339     //! Whether to print Expr's as DAGs
00340     bool dagPrinting() const { return *d_dagPrinting; }
00341     /*! @brief Return the pretty-printer if there is one; otherwise
00342        return NULL. */
00343     PrettyPrinter* getPrinter() const { return d_prettyPrinter; }
00344  
00345   /////////////////////////////////////////////////////////////////////////////
00346   // Kind registration                                                       //
00347   /////////////////////////////////////////////////////////////////////////////
00348 
00349     //! Register a new kind.
00350     /*! The kind may already be regestered under the same name, but if
00351      *  the name is different, it's an error.
00352      * 
00353      * If the new kind is supposed to represent a type, set isType to true.
00354      */
00355     void newKind(int kind, const std::string &name, bool isType = false);
00356     //! Register the pretty-printer (can only do it if none registered)
00357     /*! The pointer is NOT owned by ExprManager. Delete it yourself.
00358      */
00359     void registerPrettyPrinter(PrettyPrinter& printer);
00360     //! Tell ExprManager that the printer is no longer valid
00361     void unregisterPrettyPrinter();
00362     /*! @brief Returns true if kind is built into CVC or has been registered
00363       via newKind. */
00364     bool isKindRegistered(int kind) { return d_kindMap.count(kind) > 0; }
00365     //! Check if a kind represents a type
00366     bool isTypeKind(int kind) { return d_typeKinds.count(kind) > 0; }
00367 
00368     /*! @brief Return the name associated with a kind.  The kind must
00369       already be registered. */
00370     const std::string& getKindName(int kind);
00371     //! Return a kind associated with a name.  Returns NULL_KIND if not found.
00372     int getKind(const std::string& name);
00373     //! Register a new subclass of ExprValue
00374     /*!
00375      * Takes the size (in bytes) of the new subclass and returns the
00376      * unique index of that subclass.  Subsequent calls to the
00377      * subclass's getMMIndex() must return that index.
00378      */
00379     size_t registerSubclass(size_t sizeOfSubclass);
00380 
00381   }; // end of class ExprManager
00382 
00383 
00384 /*****************************************************************************/
00385 /*!
00386  *\class ExprManagerNotifyObj
00387  *\brief Notifies ExprManager before and after each pop()
00388  *
00389  * Author: Sergey Berezin
00390  *
00391  * Created: Tue Mar  1 12:29:14 2005
00392  *
00393  * Disables the deletion of Exprs during context restoration
00394  * (backtracking).  This solves the problem of circular dependencies,
00395  * e.g. in find pointers.
00396  */
00397 /*****************************************************************************/
00398   class ExprManagerNotifyObj: public ContextNotifyObj {
00399     ExprManager* d_em;
00400   public:
00401     //! Constructor
00402     ExprManagerNotifyObj(ExprManager* em, Context* cxt)
00403       : ContextNotifyObj(cxt), d_em(em) { }
00404 
00405     void notifyPre(void);
00406     void notify(void);
00407   };
00408     
00409 
00410 } // end of namespace CVCL
00411 
00412 // Include expr_value here for inline definitions
00413 #include "expr_value.h"
00414 
00415 namespace CVCL {
00416 
00417 inline Expr ExprManager::newLeafExpr(const Op& op)
00418 {
00419   if (op.getExpr().isNull()) {
00420     ExprValue ev(this, op.getKind());
00421     return newExpr(&ev);
00422   }
00423   else {
00424     DebugAssert(op.getExpr().getEM() == this, "ExprManager mismatch");
00425     std::vector<Expr> kids;
00426     ExprApply ev(this, op, kids);
00427     return newExpr(&ev);
00428   }
00429 }
00430 
00431 inline Expr ExprManager::newStringExpr(const std::string &s)
00432   { ExprString ev(this, s); return newExpr(&ev); }
00433 
00434 inline Expr ExprManager::newRatExpr(const Rational& r)
00435   { ExprRational ev(this, r); return newExpr(&ev); }
00436 
00437 inline Expr ExprManager::newSkolemExpr(const Expr& e, int i)
00438   { DebugAssert(e.getEM() == this, "ExprManager mismatch");
00439     ExprSkolem ev(this, i, e); return newExpr(&ev); }
00440 
00441 inline Expr ExprManager::newVarExpr(const std::string &s)
00442   { ExprVar ev(this, s); return newExpr(&ev); }
00443 
00444 inline Expr ExprManager::newSymbolExpr(const std::string &s, int kind)
00445   { ExprSymbol ev(this, kind, s); return newExpr(&ev); }
00446 
00447 inline Expr ExprManager::newBoundVarExpr(const std::string &name,
00448                                          const std::string& uid)
00449   { ExprBoundVar ev(this, name, uid); return newExpr(&ev); }
00450 
00451 inline Expr ExprManager::newBoundVarExpr(const std::string& name,
00452                                          const std::string& uid,
00453                                          const Type& type) {
00454   Expr res = newBoundVarExpr(name, uid);
00455   DebugAssert(type.getExpr().getKind() != ARROW,"");
00456   DebugAssert(res.lookupType().isNull(), 
00457               "newBoundVarExpr: redefining a variable " + name);
00458   res.setType(type);
00459   return res;
00460 }
00461 
00462 inline Expr ExprManager::newBoundVarExpr(const Type& type) {
00463   static int nextNum = 0;
00464   std::string name("_cvcl_");
00465   std::string uid =  int2string(nextNum++);
00466   return newBoundVarExpr(name, uid, type);
00467 }
00468 
00469 inline Expr ExprManager::newClosureExpr(int kind,
00470                                         const std::vector<Expr>& vars,
00471                                         const Expr& body)
00472   { ExprClosure ev(this, kind, vars, body); return newExpr(&ev); }
00473 
00474 inline size_t ExprManager::hash(const ExprValue* ev) const {
00475   DebugAssert(ev!=NULL, "ExprManager::hash() called on a NULL ExprValue");
00476   return ev->hash();
00477 }
00478 
00479 inline bool ExprManager::EqEV::operator()(const ExprValue* ev1,
00480                                           const ExprValue* ev2) const {
00481   return (*ev1) == (*ev2);
00482 }
00483 
00484 inline size_t ExprManager::hash(const Expr& e) const {
00485   DebugAssert(!e.isNull(), "ExprManager::hash() called on a Null Expr");
00486   return e.d_expr->hash();
00487 }
00488  
00489 } // end of namespace CVCL
00490 
00491 #endif
00492 

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