00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00050
00051
00052
00053 Expr Expr::recursiveSubst(const ExprHashMap<Expr>& subst,
00054 ExprHashMap<Expr>& visited) const {
00055
00056
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;
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
00079 ExprHashMap<Expr> newSubst(subst);
00080
00081 for(vector<Expr>::iterator i=common.begin(), iend=common.end();
00082 i!=iend; ++i)
00083 newSubst.erase(*i);
00084
00085
00086 visited.clear();
00087 clearFlags();
00088 visited = newSubst;
00089
00090 ExprHashMap<Expr>::iterator j = newSubst.begin();
00091 for (; j != newSubst.end(); ++j) {
00092 j->first.setFlag();
00093 }
00094
00095 replaced =
00096 getEM()->newClosureExpr(getKind(), vars,
00097 getBody().recursiveSubst(newSubst, visited));
00098
00099
00100 visited.clear();
00101 clearFlags();
00102 visited = subst;
00103
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 {
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
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
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
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
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
00181 if(oldToNew.size() == 0) return *this;
00182
00183 ExprHashMap<Expr> visited(oldToNew);
00184 clearFlags();
00185
00186
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: ;
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
00339
00340 default:
00341
00342 os << getEM()->getKindName(getKind());
00343
00344 }
00345 os.resetIndent();
00346 return os;
00347 }
00348
00349
00350
00351
00352
00353
00354
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
00421
00422 int compare(const Expr& e1, const Expr& e2) {
00423
00424
00425 if(e1 == e2) return 0;
00426
00427 if(e1.d_expr == NULL) return -1;
00428 if(e2.d_expr == NULL) return 1;
00429
00430 return (e1.getIndex() < e2.getIndex())? -1 : 1;
00431 }
00432
00433
00434
00435
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
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 }