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 #include "pretty_printer.h"
00030 #include "expr_stream.h"
00031
00032
00033 #include "theory_arith.h"
00034
00035 using namespace std;
00036
00037 namespace CVCL {
00038
00039 ExprStream::ExprStream(ExprManager *em)
00040 : d_em(em), d_os(&cout), d_depth(em->printDepth()), d_currDepth(0),
00041 d_lang(em->getOutputLang()),
00042 d_indent(em->withIndentation()), d_col(em->indent()),
00043 d_lineWidth(em->lineWidth()), d_indentReg(0), d_beginningOfLine(false),
00044 d_dag(em->dagPrinting()), d_dagBuilt(false), d_idCounter(0),
00045 d_nodag(false) {
00046 d_indentStack.push_back(d_em->indent());
00047 d_indentLast = d_indentStack.size();
00048 d_dagPtr.push_back(0);
00049 d_lastDagSize=d_dagPtr.size();
00050 }
00051
00052
00053 string ExprStream::newName() {
00054 ostringstream name;
00055 name << "cvcl_" << d_idCounter++;
00056 return name.str();
00057 }
00058
00059 static bool isTrivialExpr(const Expr& e) {
00060 switch (e.getKind()) {
00061
00062 case CONSTDEF:
00063 if (e.arity() == 2) {
00064 return isTrivialExpr(e[1]);
00065 }
00066 return false;
00067 case RATIONAL_EXPR:
00068 case PLUS:
00069 case MINUS:
00070 case UMINUS:
00071 case MULT:
00072 case DIVIDE:
00073 return true;
00074 }
00075 return (e.arity()==0 && !e.isClosure());
00076 }
00077
00078
00079 void ExprStream::collectShared(const Expr& e, ExprMap<bool>& cache) {
00080
00081 if(!isTrivialExpr(e) && cache.count(e) > 0) {
00082 if(d_dagMap.count(e) == 0) {
00083 string s(newName());
00084 if (d_lang == SMTLIB_LANG) {
00085 Type type(e.getType());
00086 if (type.isBool()) {
00087 s = "$" + s;
00088 }
00089 else {
00090 s = "?" + s;
00091 }
00092 }
00093 d_dagMap[e] = s;
00094 d_newDagMap[e] = s;
00095 d_dagStack.push_back(e);
00096 }
00097 return;
00098 }
00099 cache[e] = true;
00100 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
00101 collectShared(*i, cache);
00102 d_dagBuilt = true;
00103 }
00104
00105
00106
00107
00108
00109
00110 Expr ExprStream::addLetHeader(const Expr& e) {
00111 ExprManager* em = e.getEM();
00112 if(d_newDagMap.size() == 0) return e;
00113 vector<Expr> decls;
00114 for(ExprMap<string>::iterator i=d_newDagMap.begin(),
00115 iend=d_newDagMap.end(); i!=iend; ++i) {
00116 Expr var(em->newVarExpr((*i).second));
00117 if(((*i).first).isType())
00118 decls.push_back(Expr(LETDECL, var, em->newLeafExpr(TYPE),
00119 (*i).first));
00120 else
00121 decls.push_back(Expr(LETDECL, var, (*i).first));
00122 }
00123 d_newDagMap.clear();
00124 return Expr(LET, Expr(LETDECLS, decls), e);
00125 }
00126
00127 void ExprStream::popIndent() {
00128 DebugAssert(d_indentStack.size() > 0
00129 && d_indentStack.size() > d_indentLast,
00130 "ExprStream::popIndent(): popped too much: "
00131 "stack size = "+int2string(d_indentStack.size())
00132 +", indentLast = "+int2string(d_indentLast));
00133 if(d_indentStack.size() > 0 && d_indentStack.size() > d_indentLast)
00134 d_indentStack.pop_back();
00135 }
00136
00137
00138 void ExprStream::resetIndent() {
00139 while(d_indentStack.size() > d_indentLast)
00140 d_indentStack.pop_back();
00141 }
00142
00143
00144 void ExprStream::pushDag() {
00145 d_dagBuilt = false;
00146 d_dagPtr.push_back(d_dagStack.size());
00147 }
00148
00149 void ExprStream::popDag() {
00150 DebugAssert(d_dagPtr.size() > d_lastDagSize,
00151 "ExprStream::popDag: popping more than pushed");
00152 DebugAssert(d_lastDagSize > 0, "ExprStream::popDag: this cannot happen!");
00153 if(d_dagPtr.size() > d_lastDagSize) {
00154 size_t size(d_dagPtr.back());
00155 d_dagPtr.pop_back();
00156 while(d_dagStack.size() > size) {
00157 d_dagMap.erase(d_dagStack.back());
00158 d_dagStack.pop_back();
00159 }
00160 d_newDagMap.clear();
00161 }
00162 }
00163
00164 void ExprStream::resetDag() {
00165 while(d_dagPtr.size() > d_lastDagSize) popDag();
00166 }
00167
00168
00169
00170
00171
00172
00173 ExprStream& operator<<(ExprStream& os,
00174 ExprStream& (*manip)(ExprStream&)) {
00175 return (*manip)(os);
00176 }
00177
00178
00179 ExprStream& operator<<(ExprStream& os, const Expr& e) {
00180 Expr saveParent = os.d_parent;
00181
00182
00183 if(os.d_depth >= 0 && os.d_currDepth > os.d_depth) return os << "...";
00184 Expr e2(e);
00185
00186 switch(e.getKind()) {
00187 case QUERY:
00188 case ASSERT:
00189 case TRANSFORM:
00190 case TYPE:
00191 case CONST:
00192 os.d_nodag = true;
00193 break;
00194 default: break;
00195 }
00196
00197 if(os.d_dag && !os.d_nodag) {
00198 if(os.d_dagBuilt) {
00199 ExprMap<string>::iterator i(os.d_dagMap.find(e));
00200 if(i != os.d_dagMap.end()) {
00201 ostringstream ss;
00202 ss << (*i).second;
00203 return os << ss.str();
00204 }
00205 } else {
00206
00207 ExprMap<bool> cache;
00208 os.collectShared(e, cache);
00209 e2 = os.addLetHeader(e);
00210 }
00211 }
00212 os.d_nodag=false;
00213
00214
00215 os.d_currDepth++;
00216
00217 int indentLast = os.d_indentLast;
00218 int reg = os.d_indentReg;
00219 size_t lastDagSize = os.d_lastDagSize;
00220
00221 os.d_indentLast = os.d_indentStack.size();
00222 os.d_lastDagSize = os.d_dagPtr.size();
00223
00224 os.d_parent = os.d_current;
00225 os.d_current = e;
00226
00227 PrettyPrinter* pp = os.d_em->getPrinter();
00228
00229 if(pp == NULL || os.d_lang == AST_LANG) e2.printAST(os);
00230
00231 else pp->print(os, e2);
00232
00233 os.d_currDepth--;
00234 os.d_current = os.d_parent;
00235 os.d_parent = saveParent;
00236
00237
00238 os.resetIndent();
00239 os.resetDag();
00240 os.d_indentLast = indentLast;
00241 os.d_indentReg = reg;
00242 os.d_lastDagSize = lastDagSize;
00243 return os;
00244 }
00245
00246
00247 ExprStream& operator<<(ExprStream& os, const Type& t) {
00248 return os << t.getExpr();
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 ExprStream& operator<<(ExprStream& os, const string& s) {
00273
00274 int oldCol(os.d_col);
00275
00276 os.d_col += s.size();
00277 if(os.d_indent) {
00278
00279 int n(os.d_indentStack.size()? os.d_indentStack.back() : 0);
00280
00281 if(2*os.d_col > os.d_lineWidth && 4*(os.d_col - n) > os.d_lineWidth
00282 && 6*(oldCol - n) > os.d_lineWidth) {
00283 os << endl;
00284
00285 os.d_col += s.size();
00286 }
00287 }
00288 *os.d_os << s;
00289 os.d_beginningOfLine = false;
00290 return os;
00291 }
00292
00293
00294 ExprStream& operator<<(ExprStream& os, const char* s) {
00295 return os << string(s);
00296 }
00297
00298
00299 ExprStream& operator<<(ExprStream& os, const Rational& r) {
00300 ostringstream ss;
00301 ss << r;
00302 return os << ss.str();
00303 }
00304
00305
00306 ExprStream& operator<<(ExprStream& os, int i) {
00307 ostringstream ss;
00308 ss << i;
00309 return os << ss.str();
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319 ExprStream& push(ExprStream& os) { os.pushIndent(); return os; }
00320
00321
00322 ExprStream& pop(ExprStream& os) { os.popIndent(); return os; }
00323
00324
00325
00326
00327 ExprStream& popSave(ExprStream& os) {
00328 os.d_indentReg = os.d_indentStack.size() ? os.d_indentStack.back() : 0;
00329 os.popIndent();
00330 return os;
00331 }
00332
00333
00334
00335
00336 ExprStream& pushRestore(ExprStream& os) {
00337 os.pushIndent(os.d_indentReg);
00338 return os;
00339 }
00340
00341 ExprStream& reset(ExprStream& os) { os.resetIndent(); return os; }
00342
00343
00344
00345
00346
00347 ExprStream& space(ExprStream& os) {
00348
00349 if(!os.d_beginningOfLine) os << push << " " << pop;
00350 return os;
00351 }
00352
00353 ExprStream& nodag(ExprStream& os) {
00354 os.d_nodag = true;
00355 return os;
00356 }
00357
00358 ExprStream& pushdag(ExprStream& os) { os.pushDag(); return os; }
00359
00360 ExprStream& popdag(ExprStream& os) { os.popDag(); return os; }
00361
00362
00363
00364 }
00365
00366 namespace std {
00367
00368
00369
00370
00371
00372
00373
00374 CVCL::ExprStream& endl(CVCL::ExprStream& os) {
00375 if(os.d_indent) {
00376
00377 int n(os.d_indentStack.size()? os.d_indentStack.back() : 0);
00378
00379 string spaces(n, ' ');
00380 (*os.d_os) << endl << spaces;
00381 os.d_col = n;
00382 } else {
00383 (*os.d_os) << endl;
00384 os.d_col = 0;
00385 }
00386 os.d_beginningOfLine = true;
00387 return os;
00388 }
00389 }