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