expr_manager.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file expr_manager.cpp
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Wed Dec  4 14:20:56 2002
00008  *
00009  * <hr>
00010  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 
00029 #include "expr_manager.h"
00030 #include "command_line_flags.h"
00031 #include "expr_stream.h"
00032 #include "pretty_printer.h"
00033 #include "memory_manager_malloc.h"
00034 #include "memory_manager_chunks.h"
00035 
00036 using namespace CVCL;
00037 
00038 using namespace std;
00039 
00040 // File-local function which registers all the commonly declared
00041 // kinds (defined below)
00042 static void registerKinds(ExprManager& em);
00043 
00044 // Constructor
00045 ExprManager::ExprManager(ContextManager* cm, const CLFlags& flags)
00046   // Initial number of buckets is 1024 (it's kinda arbitrary)
00047   : d_cm(cm), d_index(0), d_flagCounter(1), d_prettyPrinter(NULL),
00048     d_printDepth(&(flags["print-depth"].getInt())),
00049     d_withIndentation(&(flags["indent"].getBool())),
00050     d_indent(0), d_indentTransient(0),
00051     d_lineWidth(&(flags["width"].getInt())),
00052     d_inputLang(&(flags["lang"].getString())),
00053     d_outputLang(&(flags["output-lang"].getString())),
00054     d_dagPrinting(&(flags["dagify-exprs"].getBool())),
00055     d_mmFlag(flags["mm"].getString()),
00056     d_exprSet(1024, HashEV(this), EqEV()),
00057     d_mm(EXPR_VALUE_TYPE_LAST),
00058     d_simpCacheTagCurrent(1), d_disableGC(false), d_postponeGC(false),
00059     d_typeComputer(NULL)
00060 {
00061   // Initialize the notifier
00062   d_notifyObj = new ExprManagerNotifyObj(this, d_cm->getCurrentContext());
00063 
00064   // Initialize core memory managers
00065   if(d_mmFlag == "chunks") {
00066     d_mm[EXPR_VALUE] = new MemoryManagerChunks(sizeof(ExprValue));
00067     d_mm[EXPR_NODE] = new MemoryManagerChunks(sizeof(ExprNode));
00068     d_mm[EXPR_APPLY] = new MemoryManagerChunks(sizeof(ExprApply));
00069     d_mm[EXPR_STRING] = new MemoryManagerChunks(sizeof(ExprString));
00070     d_mm[EXPR_RATIONAL] = new MemoryManagerChunks(sizeof(ExprRational));
00071     d_mm[EXPR_UCONST] = new MemoryManagerChunks(sizeof(ExprVar));
00072     d_mm[EXPR_SYMBOL] = new MemoryManagerChunks(sizeof(ExprSymbol));
00073     d_mm[EXPR_BOUND_VAR] = new MemoryManagerChunks(sizeof(ExprBoundVar));
00074     d_mm[EXPR_CLOSURE] = new MemoryManagerChunks(sizeof(ExprClosure));
00075     d_mm[EXPR_SKOLEM] = new MemoryManagerChunks(sizeof(ExprSkolem));
00076   } else {
00077     d_mm[EXPR_VALUE] = new MemoryManagerMalloc();
00078     d_mm[EXPR_NODE] = new MemoryManagerMalloc();
00079     d_mm[EXPR_APPLY] = new MemoryManagerMalloc();
00080     d_mm[EXPR_STRING] = new MemoryManagerMalloc();
00081     d_mm[EXPR_RATIONAL] = new MemoryManagerMalloc();
00082     d_mm[EXPR_UCONST] = new MemoryManagerMalloc();
00083     d_mm[EXPR_SYMBOL] = new MemoryManagerMalloc();
00084     d_mm[EXPR_BOUND_VAR] = new MemoryManagerMalloc();
00085     d_mm[EXPR_CLOSURE] = new MemoryManagerMalloc();
00086     d_mm[EXPR_SKOLEM] = new MemoryManagerMalloc();
00087   }
00088   registerKinds(*this);
00089   
00090   d_bool = newLeafExpr(BOOLEAN);
00091   d_false = newLeafExpr(FALSE);
00092   d_false.setType(Type::typeBool(this));
00093   d_true = newLeafExpr(TRUE);
00094   d_true.setType(Type::typeBool(this));
00095 
00096   IF_DEBUG(d_inRebuild = false);
00097 }
00098 
00099 // Destructor
00100 ExprManager::~ExprManager() {
00101   DebugAssert(d_emptyVec.size()==0, "~ExprManager()");
00102   delete d_notifyObj;
00103   // Make sure garbage collector doesn't get in the way
00104   d_disableGC = false;          //  clear() will assert this.
00105   clear();
00106   d_disableGC = true;
00107   // Destroy memory managers
00108   TRACE_MSG("delete", "~ExprManager: deleting d_mm's {");
00109   for(size_t i=0; i<d_mm.size(); ++i)
00110     delete d_mm[i];
00111 
00112   TRACE_MSG("delete", "~ExprManager: finished deleting d_mm's }");
00113 }
00114 
00115 
00116 void ExprManager::clear() {
00117   DebugAssert(isActive(), "ExprManager::clear()");
00118   // Make ExprManager inactive, but keep all the Exprs intact
00119   // Remove all internal expressions.
00120   d_disableGC = true;
00121 
00122   TRACE("delete", "clear: number of remaining Exprs: ",
00123         d_exprSet.size(), flush);
00124 
00125   DebugAssert(d_nullExpr.isNull(), "ExprManager::clear()");
00126 
00127   // Set class-local Exprs to Null
00128   d_bool = Expr();
00129   d_false = Expr();
00130   d_true = Expr();
00131 
00132   // Save all the pointers, clear the hash set, then free the
00133   // pointers.  Erasing one pointer at a time requires rehashing,
00134   // which will segfault if some pointers are already deleted.
00135   vector<ExprValue*> exprs;
00136   exprs.reserve(d_exprSet.size());
00137   TRACE_MSG("delete", "clear:() collecting exprs { ");
00138   IF_DEBUG(int n(0));
00139   for(ExprValueSet::iterator i=d_exprSet.begin(), iend=d_exprSet.end();
00140       i!=iend; ++i) {
00141     TRACE("delete", "expr[", n++, "]");
00142     exprs.push_back(*i);
00143   }
00144   TRACE_MSG("delete", "clear(): finished collecting exprs }");
00145   d_exprSet.clear();
00146   TRACE_MSG("delete", "clear(): deleting exprs { ");
00147   for(vector<ExprValue*>::iterator i=exprs.begin(), iend=exprs.end();
00148       i!=iend; ++i) {
00149     ExprValue *pExpr= *i;
00150     size_t tp(pExpr->getMMIndex()); // which memory manager to use
00151     delete (pExpr);
00152     d_mm[tp]->deleteData(pExpr);
00153   }
00154   TRACE_MSG("delete", "clear(): finished deleting exprs }");
00155 
00156 }
00157 
00158 
00159 bool ExprManager::isActive() { return !d_disableGC; }
00160 
00161 
00162 // Garbage collect the ExprValue pointer
00163 void ExprManager::gc(ExprValue* ev) {
00164   if(!d_disableGC) {
00165     d_exprSet.erase(ev);
00166     if(d_postponeGC) d_postponed.push_back(ev);
00167     else {
00168       size_t tp(ev->getMMIndex());
00169       delete ev;
00170       d_mm[tp]->deleteData(ev);
00171     }
00172   }
00173 }
00174 
00175 void
00176 ExprManager::resumeGC() {
00177   d_postponeGC = false; 
00178   while(d_postponed.size()>0) {
00179     ExprValue* ev = d_postponed.back();
00180     size_t tp(ev->getMMIndex());
00181     d_postponed.pop_back();
00182     delete ev;
00183     d_mm[tp]->deleteData(ev);
00184   }
00185 }
00186 
00187 
00188 // Rebuild the Expr with this ExprManager if it belongs to another
00189 // ExprManager
00190 Expr ExprManager::rebuild(const Expr& e) {
00191   TRACE("expr", "rebuild(", e, ") {");
00192   // Shouldn't rebuild a Null Expr (it's a bug)
00193   DebugAssert(!e.isNull(), "ExprManager::rebuild called on Null Expr");
00194   // Both ExprManagers must be active
00195   DebugAssert(isActive() && e.getEM()->isActive(),
00196               "ExprManager::rebuild is called on inactive ExprManager");
00197   // If e has the same ExprManager, no rebuilding is necessary
00198   if(e.isNull() || (e.getEM() == this)) {
00199     TRACE_MSG("expr", "rebuild (same EM) => }");
00200     return e;
00201   }
00202   // Gotta rebuild
00203   DebugAssert(!d_inRebuild, "ExprManager::rebuild()");
00204   IF_DEBUG(ScopeWatcher sw(&d_inRebuild));
00205   // First, clear the cache
00206   if(d_rebuildCache.size() > 0) d_rebuildCache.clear();
00207   Expr res = rebuildRec(e);
00208   // Leave no trail behind (free up Exprs)
00209   if(d_rebuildCache.size() > 0) d_rebuildCache.clear();
00210   TRACE("expr", "rebuild => ", e, " }");
00211   return res;
00212 }
00213 
00214 
00215 Expr ExprManager::rebuildRec(const Expr& e) {
00216   DebugAssert(d_inRebuild, "ExprManager::rebuildRec("+e.toString()+")");
00217   // Check cache
00218   ExprHashMap<Expr>::iterator j=d_rebuildCache.find(e),
00219     jend=d_rebuildCache.end();
00220   if(j!=jend) return (*j).second;
00221   
00222   ExprValue* ev = e.d_expr->rebuild(this);
00223   // Uniquify the pointer
00224   ExprValueSet::iterator i(d_exprSet.find(ev)), iend(d_exprSet.end());
00225   if(i != iend) {
00226     MemoryManager* mm = getMM(ev->getMMIndex());
00227     delete ev;
00228     mm->deleteData(ev);
00229     ev = *i;
00230   } else {
00231     ev->setIndex(nextIndex());
00232     installExprValue(ev);
00233   }
00234   // Use non-uniquifying Expr() constructor
00235   Expr res(ev);
00236   // Cache the result
00237   d_rebuildCache[e] = res;
00238 
00239   // Rebuild the type too
00240   Type t;
00241   if (!e.d_expr->d_type.isNull()) {
00242     t = Type(rebuildRec(e.d_expr->d_type.getExpr()));
00243   }
00244   if (ev->d_type.isNull()) ev->d_type = t;
00245   else if (ev->d_type != t) {
00246     throw Exception("Types don't match in rebuildRec");
00247   }
00248 
00249   return res;
00250 }
00251 
00252 
00253 ExprValue* ExprManager::newExprValue(ExprValue* ev) {
00254   DebugAssert(isActive(), "ExprManager::newExprValue(ExprValue*)");
00255   ExprValueSet::iterator i(d_exprSet.find(ev)), iend(d_exprSet.end());
00256   if(i != iend) return (*i);
00257   // No such ExprValue.  Create a clean copy, insert it into the set
00258   // and return the new pointer.
00259   ExprValue* p_ev = ev->copy(this, nextIndex());
00260   installExprValue(p_ev);
00261   return p_ev;
00262 }
00263 
00264 
00265 // ExprValue* ExprManager::newExprValue(const Expr& op,
00266 //                                   const vector<Expr>& kids) {
00267 //   // Check if op and kids have the same ExprManager
00268 //   DebugAssert(isActive(), "ExprManager::newExprValue(op, kids)");
00269 //   DebugAssert(this == op.getEM(),
00270 //            "ExprManager::newExprValue(op, kids): op is from a wrong "
00271 //            "ExprManager/ValidityChecker, call importExpr() first:\n"
00272 //            +op.toString());
00273 //   IF_DEBUG(
00274 //     for(vector<Expr>::const_iterator i=kids.begin(), iend=kids.end();
00275 //      i!=iend; ++i)
00276 //       DebugAssert(!i->isNull() && (i->getEM() == this),
00277 //                "ExprManager::newExprValue(op, kids): the child is"
00278 //                " from a wrong instance of ExprManager/ValidityChecker,"
00279 //                "call importExpr() first:\n"
00280 //                +i->toString());
00281 //     );
00282 //   ExprValue* res = op.d_expr->copy(this, kids);
00283 //   ExprValueSet::iterator i(d_exprSet.find(res)), iend(d_exprSet.end());
00284 //   if(i != iend) {
00285 //     MemoryManager* mm = getMM(res->getMMIndex());
00286 //     delete res;
00287 //     mm->deleteData(res);
00288 //     return (*i);
00289 //   } else {
00290 //     res->setIndex(nextIndex());
00291 //     installExprValue(res);
00292 //     return res;
00293 //   }
00294 // }
00295 
00296 
00297 void ExprManager::installExprValue(ExprValue* p_ev)
00298 {
00299   DebugAssert(isActive(), "ExprManager::installExprValue(ExprValue*)");
00300   int maxHeight = 0;
00301   p_ev->d_highestKid = 0;
00302   for (unsigned i = 0; i < p_ev->arity(); i++)
00303   {
00304     int height = p_ev->getKids()[i].getHeight();
00305     if (height > maxHeight)
00306     {
00307       maxHeight = height;
00308       p_ev->d_highestKid = i;
00309     }
00310   }
00311 
00312   if (p_ev->d_kind == ITE && p_ev->arity() == 3)
00313   {
00314     if (p_ev->getKids()[1].getHeight() > p_ev->getKids()[2].getHeight())
00315       p_ev->d_highestKid = 1;
00316     else
00317       p_ev->d_highestKid = 2;
00318   }
00319 
00320   switch (p_ev->d_kind) {
00321   case NOT: case AND: case OR: case ITE: case IFF: case IMPLIES:
00322     maxHeight++;
00323   }
00324   p_ev->d_height = maxHeight;
00325 
00326   d_exprSet.insert(p_ev);
00327 }
00328 
00329 //! Set initial indentation.  Returns the previous permanent value.
00330 int 
00331 ExprManager::indent(int n, bool permanent) {
00332   int ret(d_indent);
00333   d_indentTransient = n;
00334   if(permanent) d_indent = n;
00335   return ret;
00336 }
00337 
00338 //! Increment the current transient indentation by n
00339 /*! If the second argument is true, sets the result as permanent.
00340   \return previous permanent value. */
00341 int
00342 ExprManager::incIndent(int n, bool permanent) {
00343   int ret(d_indent);
00344   d_indentTransient += n;
00345   if(permanent) d_indent = d_indentTransient;
00346   return ret;
00347 }
00348 
00349 // Various options
00350 InputLanguage
00351 ExprManager::getInputLang() const {
00352   string lang;
00353   if(d_inputLang->size() > 0) lang = d_inputLang->substr(0,1);
00354   return getLanguage(lang);
00355 }
00356  
00357 
00358 InputLanguage
00359 ExprManager::getOutputLang() const {
00360   const std::string* langPtr
00361     = (*d_outputLang == "")? d_inputLang : d_outputLang;
00362   std::string lang;
00363   if(langPtr->size() > 0) lang = langPtr->substr(0,1);
00364   return getLanguage(lang);
00365 }
00366 
00367 
00368 // Register a new kind.  The kind may already be regestered under
00369 // the same name, but if the name is different, it's an error.
00370 void ExprManager::newKind(int kind, const string &name, bool isType) {
00371   if(d_kindMap.count(kind) == 0) {
00372     d_kindMap[kind] = name;
00373     if(isType) d_typeKinds.insert(kind);
00374   }
00375   else if(d_kindMap[kind] != name) {
00376     DebugAssert(false, "CVCL::ExprManager::newKind(kind = "
00377                 + int2string(kind) + ", name = " + name
00378                 + "): \n" + 
00379                 "this kind is already registered with a different name: "
00380                 + d_kindMap[kind]);
00381   }
00382   if(d_kindMapByName.count(name) == 0)
00383     d_kindMapByName[name] = kind;
00384   else if(d_kindMapByName[name] != kind) {
00385     DebugAssert(false, "CVCL::ExprManager::newKind(kind = "
00386                 + int2string(kind) + ", name = " + name
00387                 + "): \n" + 
00388                 "this kind name is already registered with a different index: "
00389                 + int2string(d_kindMapByName[name]));
00390   }
00391 }
00392 
00393 // Register a printer
00394 void ExprManager::registerPrettyPrinter(PrettyPrinter& printer) {
00395   DebugAssert(d_prettyPrinter==NULL, "ExprManager:registerPrettyPrinter():"
00396               " printer is already registered");
00397   d_prettyPrinter = &printer;
00398 }
00399 
00400 // Unregister a printer
00401 void ExprManager::unregisterPrettyPrinter() {
00402   DebugAssert(d_prettyPrinter!=NULL, "ExprManager:unregisterPrettyPrinter():"
00403               " printer is not registered");
00404   d_prettyPrinter = NULL;
00405 }
00406 
00407 
00408 const string& ExprManager::getKindName(int kind) {
00409   DebugAssert(d_kindMap.count(kind) > 0,
00410               ("CVCL::ExprManager::getKindName(kind = "
00411                + int2string(kind) + "): kind is not registered.").c_str());
00412   return d_kindMap[kind];
00413 }
00414 
00415 int ExprManager::getKind(const string& name) {
00416   std::hash_map<std::string, int, HashString>::iterator
00417     i=d_kindMapByName.find(name),
00418     iend=d_kindMapByName.end();
00419   if(i==iend) return NULL_KIND;
00420   else return (*i).second;
00421 }
00422 
00423 
00424 size_t ExprManager::registerSubclass(size_t sizeOfSubclass) {
00425   size_t idx(d_mm.size());
00426   if(d_mmFlag == "chunks")
00427     d_mm.push_back(new MemoryManagerChunks(sizeOfSubclass));
00428   else
00429     d_mm.push_back(new MemoryManagerMalloc());
00430 
00431   FatalAssert(d_mm.back() != NULL, "Out of memory");
00432   return idx;
00433 }
00434 
00435 
00436 void ExprManager::computeType(const Expr& e) {
00437   DebugAssert(d_typeComputer, "No type computer installed");
00438   d_typeComputer->computeType(e);
00439   DebugAssert(!e.getType().getExpr().isNull(), "Type not set by computeType");
00440 }
00441 
00442 
00443 void ExprManager::checkType(const Expr& e) {
00444   DebugAssert(d_typeComputer, "No type computer installed");
00445   if (!e.isValidType()) d_typeComputer->checkType(e);
00446   DebugAssert(e.isValidType(), "Type not checked by checkType");
00447 }
00448 
00449 
00450 // Kind registration macro
00451 #define REG(k) em.newKind(k, #k)
00452 #define REG_TYPE(k) em.newKind(k, #k, true)
00453 
00454 static void registerKinds(ExprManager& em) {
00455   // Register type kinds
00456   REG_TYPE(BOOLEAN);
00457   //  REG(TUPLE_TYPE);
00458   REG_TYPE(ARROW);
00459   REG_TYPE(TYPE);
00460   REG_TYPE(TYPEDECL);
00461   REG_TYPE(TYPEDEF);
00462   REG_TYPE(SUBTYPE);
00463 
00464   // Register expression (non-type) kinds 
00465   REG(NULL_KIND);
00466 
00467   REG(RAW_LIST);
00468   REG(STRING_EXPR);
00469   REG(RATIONAL_EXPR);
00470   REG(TRUE);
00471   REG(FALSE);
00472   
00473   REG(EQ);
00474   REG(NEQ);
00475   
00476   REG(NOT);
00477   REG(AND);
00478   REG(OR);
00479   REG(XOR);
00480   REG(IFF);
00481   REG(IMPLIES);
00482 
00483   REG(AND_R);
00484   REG(IFF_R);
00485   REG(ITE_R);
00486 
00487   REG(ITE);
00488   
00489   REG(FORALL);
00490   REG(EXISTS);
00491   
00492   REG(UFUNC);
00493   REG(APPLY);
00494 
00495   REG(ASSERT);
00496   REG(QUERY);
00497   REG(CHECKSAT);
00498   REG(CONTINUE);
00499   REG(RESTART);
00500   REG(DBG);
00501   REG(TRACE);
00502   REG(UNTRACE);
00503   REG(OPTION);
00504   REG(HELP);
00505   REG(TRANSFORM);
00506   REG(PRINT);
00507   REG(CALL);
00508   REG(ECHO);
00509   REG(INCLUDE);
00510   REG(DUMP_PROOF);
00511   REG(DUMP_ASSUMPTIONS);
00512   REG(DUMP_SIG);
00513   REG(DUMP_TCC);
00514   REG(DUMP_TCC_ASSUMPTIONS);
00515   REG(DUMP_TCC_PROOF);
00516   REG(DUMP_CLOSURE);
00517   REG(DUMP_CLOSURE_PROOF);
00518   REG(WHERE);
00519   REG(ASSERTIONS);
00520   REG(ASSUMPTIONS);
00521   REG(COUNTEREXAMPLE);
00522   REG(COUNTERMODEL);
00523   REG(PUSH);
00524   REG(POP);
00525   REG(POPTO);
00526   REG(PUSH_SCOPE);
00527   REG(POP_SCOPE);
00528   REG(POPTO_SCOPE);
00529   REG(CONTEXT);
00530   REG(FORGET);
00531   REG(GET_TYPE);
00532   REG(CHECK_TYPE);
00533   REG(GET_CHILD);
00534   REG(SUBSTITUTE);
00535   REG(SEQ);
00536 
00537   // Kinds used mostly in the parser
00538 
00539   REG(TCC);
00540   REG(ID);
00541   REG(VARDECL);
00542   REG(VARDECLS);
00543 
00544 
00545   REG(BOUND_VAR);
00546   REG(BOUND_ID);
00547 
00548   REG(SKOLEM_VAR);
00549 
00550 //   REG(UPDATE);
00551 //   REG(UPDATE_SELECT);
00552 
00553 //   REG(RECORD_TYPE);
00554 //   REG(RECORD);
00555 //   REG(RECORD_SELECT);
00556 //   REG(RECORD_UPDATE);
00557 
00558 //   REG(TUPLE);
00559 //   REG(TUPLE_SELECT);
00560 //   REG(TUPLE_UPDATE);
00561 
00562 //   REG(SUBRANGE);
00563 
00564 //   REG(SCALARTYPE);
00565 //   REG(DATATYPE);
00566 //   REG(THISTYPE);
00567 //   REG(CONSTRUCTOR);
00568 //   REG(SELECTOR);
00569 //   REG(TESTER);
00570   //  REG(DATATYPE_UPDATE);
00571 
00572   REG(IF);
00573   REG(IFTHEN);
00574   REG(ELSE);
00575   REG(COND);
00576 
00577   REG(LET);
00578   REG(LETDECLS);
00579   REG(LETDECL);
00580 
00581   REG(LAMBDA);
00582   REG(SIMULATE);
00583 
00584   REG(CONSTDEF);
00585 
00586   REG(CONST);
00587   REG(VARLIST);
00588   REG(UCONST);
00589   REG(DEFUN);
00590 
00591   // Arithmetic types and operators
00592 //   REG(REAL);
00593 //   REG(INT);
00594 
00595 //   REG(UMINUS);
00596 //   REG(PLUS);
00597 //   REG(MINUS);
00598 //   REG(MULT);
00599 //   REG(DIVIDE);
00600 //   REG(POW);
00601 //   REG(INTDIV);
00602 //   REG(MOD);
00603 //   REG(LT);
00604 //   REG(LE);
00605 //   REG(GT);
00606 //   REG(GE);
00607 //   REG(IS_INTEGER);
00608 //   REG(NEGINF);
00609 //   REG(POSINF);
00610 //   REG(FLOOR);
00611 }
00612 
00613 
00614 void ExprManagerNotifyObj::notifyPre() {
00615   d_em->postponeGC();
00616 }
00617 
00618 
00619 void ExprManagerNotifyObj::notify() {
00620   d_em->resumeGC();
00621 }

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