expr.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file expr.cpp
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Thu Dec  5 11:35:55 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 
00030 #include <algorithm>
00031 
00032 
00033 #include "expr.h"
00034 #include "pretty_printer.h"
00035 #include "expr_stream.h"
00036 #include "notifylist.h"
00037 #include "exception.h"
00038 
00039 
00040 using namespace std;
00041 
00042 
00043 namespace CVCL {
00044 
00045 
00046 Expr Expr::s_null;
00047 
00048 ///////////////////////////////////////////////////////////////////////
00049 // Class Expr methods                                                //
00050 ///////////////////////////////////////////////////////////////////////
00051 
00052 
00053 Expr Expr::recursiveSubst(const ExprHashMap<Expr>& subst,
00054                           ExprHashMap<Expr>& visited) const {
00055   // Check the cache.
00056   // INVARIANT: visited contains all the flagged expressions, and only those
00057   if(getFlag()) return visited[*this];
00058 
00059   ExprIndex minIndex = 0;
00060   for(ExprHashMap<Expr>::iterator i = subst.begin(),iend=subst.end();i!=iend;++i) {
00061     if(minIndex > (i->first).getIndex())
00062       minIndex = (i->first).getIndex();
00063   }
00064 
00065   Expr replaced;
00066 
00067   if(isClosure()) {
00068     const vector<Expr> & vars = getVars();
00069     vector<Expr> common; // Bound vars which occur in subst
00070 
00071     for(vector<Expr>::const_iterator i = vars.begin(), iend=vars.end();
00072         i!=iend; ++i) {
00073       if(subst.count(*i) > 0) common.push_back(*i);
00074     }
00075 
00076     if(common.size() > 0) {
00077       IF_DEBUG(debugger.counter("substExpr: bound var clashes")++);
00078       // Reduced substitution (without the common vars)
00079       ExprHashMap<Expr> newSubst(subst);
00080       // Remove variables in "common" from the substitution
00081       for(vector<Expr>::iterator i=common.begin(), iend=common.end();
00082           i!=iend; ++i)
00083         newSubst.erase(*i);
00084 
00085       // Clear all the caches (important!)
00086       visited.clear();
00087       clearFlags();
00088       visited = newSubst;
00089 
00090       ExprHashMap<Expr>::iterator j = newSubst.begin();
00091       for (; j != newSubst.end(); ++j) { // old vars bound in e
00092         j->first.setFlag();
00093       }
00094     
00095       replaced = 
00096         getEM()->newClosureExpr(getKind(), vars,
00097                                 getBody().recursiveSubst(newSubst, visited));
00098 
00099       // Clear the flags again, as we restore the substitution
00100       visited.clear();
00101       clearFlags();
00102       visited = subst;
00103       // Restore the flags on the original substitutions
00104       for (ExprHashMap<Expr>::iterator i = subst.begin(), iend=subst.end();
00105            i != iend; ++i)
00106         i->first.setFlag();
00107     } else {
00108       replaced =
00109         getEM()->newClosureExpr(getKind(), vars,
00110                                 getBody().recursiveSubst(subst, visited));
00111     }
00112   } else { // Not a Closure
00113       int changed=0;
00114       vector<Expr> children;      
00115       for(Expr::iterator i=begin(), iend=end(); i!=iend; ++i){  
00116         Expr repChild = *i;
00117         if(repChild.getIndex() >= minIndex)
00118           repChild = (*i).recursiveSubst(subst, visited);
00119         if(repChild != *i)
00120           changed++;
00121         children.push_back(repChild);
00122       }
00123       if(changed > 0)
00124         replaced = Expr(getOp(), children);
00125       else
00126         replaced = *this;
00127   }
00128   visited.insert(*this, replaced);
00129   setFlag();
00130   return replaced;
00131 }
00132 
00133 
00134 static bool subExprRec(const Expr& e1, const Expr& e2) {
00135   if(e1 == e2) return true;
00136   if(e2.getFlag()) return false;
00137   // e1 is created after e2, so e1 cannot be a subexpr of e2
00138   if(e1 > e2) return false;
00139   e2.setFlag();
00140   bool res(false);
00141   for(Expr::iterator i=e2.begin(), iend=e2.end(); !res && i!=iend; ++i)
00142     res = subExprRec(e1, *i);
00143   return res;
00144 }
00145 
00146 
00147 bool 
00148 Expr::subExprOf(const Expr& e) const {
00149   if(*this == e) return true;
00150   // "this" is created after e, so it cannot be e's subexpression
00151   if(*this > e) return false;
00152   clearFlags();
00153   return subExprRec(*this, e);
00154 }
00155 
00156 
00157 Expr Expr::substExpr(const vector<Expr>& oldTerms,
00158                      const vector<Expr>& newTerms) const
00159 {
00160   DebugAssert(oldTerms.size() == newTerms.size(), "substExpr: vectors"
00161               "don't match in size");
00162   // Catch the vacuous case
00163   if(oldTerms.size() == 0) return *this;
00164 
00165   ExprHashMap<Expr> oldToNew(10);
00166   clearFlags();
00167   for(unsigned int i=0; i<oldTerms.size(); i++) {
00168     oldToNew.insert(oldTerms[i], newTerms[i]);
00169     oldTerms[i].setFlag();
00170   }
00171   // For cache, initialized by the substitution
00172   ExprHashMap<Expr> visited(oldToNew);
00173   return recursiveSubst(oldToNew, visited);
00174 
00175 }
00176 
00177 
00178 Expr Expr::substExpr(const ExprHashMap<Expr>& oldToNew) const
00179 {
00180   // Catch the vacuous case
00181   if(oldToNew.size() == 0) return *this;
00182   // Rebuild the map: we'll be using it as a cache
00183   ExprHashMap<Expr> visited(oldToNew);
00184   clearFlags();
00185   // Flag all the LHS expressions in oldToNew map.  We'll be checking
00186   // all flagged expressions (and only those) for substitution.
00187   for(ExprHashMap<Expr>::iterator i=oldToNew.begin(), iend=oldToNew.end();
00188       i!=iend; ++i) {
00189     (*i).first.setFlag();
00190   }
00191   return recursiveSubst(oldToNew, visited);
00192 }
00193 
00194 
00195 string Expr::toString() const {
00196   if(isNull()) return "Null";
00197   ostringstream ss;
00198   ss << (*this);
00199   return ss.str();
00200 }
00201 
00202 string Expr::toString(InputLanguage lang) const {
00203   if(isNull()) return "Null";
00204   ostringstream ss;
00205   ExprStream os(getEM());
00206   os.lang(lang);
00207   os.os(ss);
00208   os << (*this);
00209   return ss.str();
00210 }
00211 
00212 void Expr::print(InputLanguage lang, bool dagify) const {
00213   if(isNull()) {
00214     cout << "Null" << endl; return;
00215   }
00216   ExprStream os(getEM());
00217   os.lang(lang);
00218   os.dagFlag(dagify);
00219   os << *this << endl;
00220 }
00221 
00222 
00223 void Expr::pprint() const
00224 {
00225   if(isNull()) {
00226     cout << "Null" << endl; return;
00227   }
00228   ExprStream os(getEM());
00229   os << *this << endl;
00230 }
00231 
00232 
00233 void Expr::pprintnodag() const
00234 {
00235   if(isNull()) {
00236     cout << "Null" << endl; return;
00237   }
00238   ExprStream os(getEM());
00239   os.dagFlag(false);
00240   os << *this << endl;
00241 }
00242 
00243 
00244 void Expr::printnodag() const
00245 {
00246   print(AST_LANG, false);
00247 }
00248 
00249 
00250 ExprStream& Expr::printAST(ExprStream& os) const {
00251   if(isNull()) return os << "Null" << endl;
00252   bool isLetDecl(getKind() == LETDECL);
00253   os << "(" << push;
00254   os << getEM()->getKindName(getKind());
00255   if (isApply()) {
00256     os << space << "{" << getOp().getExpr() << push << "}";
00257   }
00258   else if (isSymbol()) {
00259     os << space << "{Symbol: " << getName() << "}";
00260   }
00261   else if (isClosure()) {
00262     os << space << "{" << space << "(" << push;
00263     const vector<Expr>& vars = getVars();
00264     vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
00265     if(i!=iend) { os << *i; ++i; }
00266     for(; i!=iend; ++i) os << space << *i;
00267     os << push << ") " << pop << pop;
00268     os << getBody() << push << "}";
00269   }
00270   else {
00271     switch(getKind()) {
00272       case STRING_EXPR:
00273         DebugAssert(isString(), "Expected String");
00274         os << space << "{" << '"'+ getString() + '"' << "}";
00275         break;
00276       case SKOLEM_VAR:
00277         getExistential();
00278         os << space << "{SKOLEM_" << getIndex() << "}";
00279         break;
00280       case RATIONAL_EXPR:
00281         os << space << "{" << getRational() << "}";
00282         break;
00283       case UCONST: 
00284         DebugAssert(isVar(), "Expected Var");
00285         os << space << "{" << getName() << "}";
00286         break;
00287       case BOUND_VAR:
00288         DebugAssert(isVar(), "Expected Var");
00289         os << space << "{"+getName()+"_"+getUid()+"}";
00290         break;
00291       default: ; // Don't do anything
00292     }
00293   }
00294 
00295   for(Expr::iterator i=begin(), iend=end(); i!=iend; ++i) {
00296     if(isLetDecl) os << nodag;
00297     os << space << *i;
00298   }
00299   os << push << ")";
00300   os.resetIndent();
00301   return os;
00302 }
00303 
00304 
00305 ExprStream& Expr::print(ExprStream& os) const {
00306   if(isNull()) return os << "Null" << endl;
00307   DebugAssert(arity() == 0, "Expected arity 0");
00308   if (isSymbol()) return os << getName();
00309   switch(getKind()) {
00310   case NULL_KIND: return os << "Null";
00311   case STRING_EXPR: return os << '"'+ getString() + '"';
00312   case RATIONAL_EXPR: return os << getRational();
00313   case SKOLEM_VAR: return os << "SKOLEM_" <<  hash();
00314   case UCONST: return os << getName();
00315   case BOUND_VAR: return os << "(BOUND_VAR "+getName()+"_"+getUid()+")";
00316   case RAW_LIST: {
00317     os << "(" << push;
00318     bool firstTime(true);
00319     for(Expr::iterator i=begin(), iend=end(); i!=iend; ++i) {
00320       if(firstTime) firstTime = false;
00321       else os << space;
00322       os << *i;
00323     }
00324     return os << push << ")";
00325   }
00326   case FORALL:
00327   case EXISTS: 
00328     if(isQuantifier()) {
00329       os << "(" << push << getEM()->getKindName(getKind())
00330          << space << "(" << push;
00331       const vector<Expr>& vars = getVars();
00332       vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
00333       if(i!=iend) { os << *i; ++i; }
00334       for(; i!=iend; ++i) os << space << *i;
00335       os << push << ") " << pop << pop;
00336       return os << getBody() << push << ")";
00337     }
00338     // If not an internal representation of quantifiers, it'll be
00339     // printed as "normal" Expr with a kind and children
00340   default:
00341     //    os << "(" << push;
00342     os << getEM()->getKindName(getKind());
00343     //    os << push << ")";
00344   }
00345   os.resetIndent();
00346   return os;
00347 }
00348 
00349 
00350 //! Set initial indentation to n.
00351 /*! The indentation will be reset to default unless the second
00352     argument is true.  This setting only takes effect when printing to
00353     std::ostream.  When printing to ExprStream, the indentation can be
00354     set directly in the ExprStream. */
00355 Expr& Expr::indent(int n, bool permanent) {
00356   DebugAssert(!isNull(), "Expr::indent called on Null Expr");
00357   getEM()->indent(n, permanent);
00358   return *this;
00359 }
00360 
00361 
00362 void Expr::addToNotify(Theory* i, const Expr& e) const {
00363   DebugAssert(!isNull(), "Expr::addToNotify() on Null expr");
00364   if(getNotify() == NULL)
00365     d_expr->d_notifyList = new NotifyList(getEM()->getCurrentContext());
00366   getNotify()->add(i, e);
00367 }
00368 
00369 
00370 bool Expr::isAtomic() const
00371 {
00372   TRACE("isAtomic", "isAtomic(", *this, ") {");
00373   if (validIsAtomicFlag()) {
00374     TRACE("isAtomic", "isAtomic[cached] => ",
00375           getIsAtomicFlag()? "true" : "false", " }");
00376     return getIsAtomicFlag();
00377   }
00378   if (getType().isBool() && !isBoolConst()) {
00379     setIsAtomicFlag(false);
00380     TRACE_MSG("isAtomic", "isAtomic[bool] => false }");
00381     return false;
00382   }
00383   for (int k = 0; k < arity(); ++k) {
00384     if (!(*this)[k].isAtomic()) {
00385       setIsAtomicFlag(false);
00386       TRACE_MSG("isAtomic", "isAtomic[kid] => false }");
00387       return false;
00388     }
00389   }
00390   setIsAtomicFlag(true);
00391   TRACE_MSG("isAtomic", "isAtomic[kid] => true }");
00392   return true;
00393 }
00394 
00395 
00396 bool Expr::isAtomicFormula() const
00397 {
00398   TRACE("isAtomic", "isAtomicFormula(", *this, ") {");
00399   if (!getType().isBool()) {
00400     TRACE_MSG("isAtomic", "isAtomicFormula[kid] => false }");
00401     return false;
00402   }
00403   switch(getKind()) {
00404     case FORALL: case EXISTS: case XOR:
00405     case NOT: case AND: case OR: case ITE: case IFF: case IMPLIES:
00406       TRACE_MSG("isAtomic", "isAtomicFormula[connective] => false }");
00407       return false;
00408   }
00409   for (Expr::iterator k = begin(), kend=end(); k != kend; ++k) {
00410     if (!(*k).isAtomic()) {
00411       TRACE_MSG("isAtomic", "isAtomicFormula[kid] => false }");
00412       return false;
00413     }
00414   }
00415   TRACE_MSG("isAtomic", "isAtomicFormula => true }");
00416   return true;
00417 }
00418 
00419 
00420   // This is one of the most friequently called routines.  Make it as
00421   // efficient as possible.
00422 int compare(const Expr& e1, const Expr& e2) {
00423   // Quick equality check (operator== is implemented independently
00424   // and more efficiently)
00425   if(e1 == e2) return 0;
00426     
00427   if(e1.d_expr == NULL) return -1;
00428   if(e2.d_expr == NULL) return 1;
00429   // Both are non-Null.  Compare the indices.
00430   return (e1.getIndex() < e2.getIndex())? -1 : 1;
00431 }
00432 
00433 
00434 ///////////////////////////////////////////////////////////////////////
00435 // Class Expr::iterator methods                                      //
00436 ///////////////////////////////////////////////////////////////////////
00437 
00438 const Expr& Expr::iterator::operator*() const {
00439   return *d_it;
00440 }
00441 
00442 const Expr* Expr::iterator::operator->() const {
00443   return &(operator*());
00444 }
00445 
00446 
00447 Expr::iterator Expr::begin() const {
00448   if(arity() > 0)
00449     return iterator(getKids().begin());
00450   else
00451     return iterator(getEM()->getEmptyVector().begin());
00452 }
00453 
00454 
00455 Expr::iterator Expr::end() const {
00456   if(arity() > 0)
00457     return iterator(getKids().end());
00458   else
00459     return iterator(getEM()->getEmptyVector().end());
00460 }
00461 
00462 
00463 ostream& operator<<(ostream& os, const Expr& e) {
00464   if(e.isNull()) return os << "Null";
00465   ExprStream es(e.getEM());
00466   es.os(os);
00467   es << e;
00468   e.getEM()->restoreIndent();
00469   return os;
00470 }
00471 
00472 
00473 // Functions from class Type
00474 
00475 
00476 Type::Type(Expr expr) : d_expr(expr)
00477 {
00478   if (expr.isNull()) return;
00479   expr.getEM()->checkType(expr);
00480 }
00481 
00482 
00483 Type Type::funType(const std::vector<Type>& typeDom, const Type& typeRan) {
00484   vector<Expr> tmp;
00485   for(vector<Type>::const_iterator i=typeDom.begin(), iend=typeDom.end();
00486       i!=iend; ++i)
00487     tmp.push_back(i->getExpr());
00488   tmp.push_back(typeRan.getExpr());
00489   return Type(Expr(ARROW, tmp));
00490 }
00491 
00492 
00493 } // end of namespace CVCL

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