#include "expr/sequence.h"
#include "options/language.h" // for LANG_AST
#include "options/smt_options.h"
-#include "printer/dagification_visitor.h"
+#include "printer/let_binding.h"
#include "smt/command.h"
#include "smt/node_command.h"
#include "smt/smt_engine.h"
size_t dag) const
{
if(dag != 0) {
- DagificationVisitor dv(dag);
- NodeVisitor<DagificationVisitor> visitor;
- visitor.run(dv, n);
- const theory::SubstitutionMap& lets = dv.getLets();
- if(!lets.empty()) {
- out << "LET ";
- bool first = true;
- for(theory::SubstitutionMap::const_iterator i = lets.begin();
- i != lets.end();
- ++i) {
- if(! first) {
- out << ", ";
- } else {
- first = false;
- }
- toStream(out, (*i).second, toDepth, false);
- out << " = ";
- toStream(out, (*i).first, toDepth, false);
- }
- out << " IN ";
- }
- Node body = dv.getDagifiedBody();
- toStream(out, body, toDepth, false);
+ LetBinding lbind(dag + 1);
+ toStreamNodeWithLetify(out, n, toDepth, false, &lbind);
} else {
- toStream(out, n, toDepth, false);
+ toStreamNode(out, n, toDepth, false, nullptr);
}
}
}
}
-void CvcPrinter::toStream(std::ostream& out,
- TNode n,
- int depth,
- bool bracket) const
+void CvcPrinter::toStreamNode(std::ostream& out,
+ TNode n,
+ int depth,
+ bool bracket,
+ LetBinding* lbind) const
{
if (depth == 0) {
out << "(...)";
break;
case kind::ITE:
out << "IF ";
- toStream(out, n[0], depth, true);
+ toStreamNode(out, n[0], depth, true, lbind);
out << " THEN ";
- toStream(out, n[1], depth, true);
+ toStreamNode(out, n[1], depth, true, lbind);
out << " ELSE ";
- toStream(out, n[2], depth, true);
+ toStreamNode(out, n[2], depth, true, lbind);
out << " ENDIF";
return;
break;
if (i > 0) {
out << ", ";
}
- toStream(out, n[i], depth, false);
+ toStreamNode(out, n[i], depth, false, lbind);
}
out << ']';
return;
break;
case kind::LAMBDA:
out << "(LAMBDA";
- toStream(out, n[0], depth, true);
+ toStreamNode(out, n[0], depth, true, lbind);
out << ": ";
- toStream(out, n[1], depth, true);
+ toStreamNodeWithLetify(out, n[1], depth, true, lbind);
out << ")";
return;
break;
case kind::WITNESS:
out << "(WITNESS";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, true, lbind);
out << " : ";
- toStream(out, n[1], depth, false);
+ toStreamNodeWithLetify(out, n[1], depth, true, lbind);
out << ')';
return;
case kind::DISTINCT:
// distinct not supported directly, blast it away with the rewriter
- toStream(out, theory::Rewriter::rewrite(n), depth, true);
+ toStreamNode(out, theory::Rewriter::rewrite(n), depth, true, lbind);
return;
case kind::SORT_TYPE:
{
break;
// UF
- case kind::APPLY_UF: toStream(op, n.getOperator(), depth, false); break;
+ case kind::APPLY_UF:
+ toStreamNode(op, n.getOperator(), depth, false, lbind);
+ break;
case kind::CARDINALITY_CONSTRAINT:
case kind::COMBINED_CARDINALITY_CONSTRAINT:
out << "CARDINALITY_CONSTRAINT";
if (i > 1) {
out << ", ";
}
- toStream(out, n[i - 1], depth, false);
+ toStreamNode(out, n[i - 1], depth, false, lbind);
}
if (n.getNumChildren() > 2) {
out << ')';
}
}
out << " -> ";
- toStream(out, n[n.getNumChildren() - 1], depth, false);
+ toStreamNode(out, n[n.getNumChildren() - 1], depth, false, lbind);
return;
break;
return;
break;
case kind::APPLY_TYPE_ASCRIPTION: {
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << "::";
TypeNode t = n.getOperator().getConst<AscriptionType>().getType();
out << (t.isFunctionLike() ? t.getRangeType() : t);
out << ", ";
}
out << recCons[i].getName() << " := ";
- toStream(out, n[i], depth, false);
+ toStreamNode(out, n[i], depth, false, lbind);
}
out << " #)";
return;
}
else
{
- toStream(op, n.getOperator(), depth, false);
+ toStreamNode(op, n.getOperator(), depth, false, lbind);
if (n.getNumChildren() == 0)
{
// for datatype constants d, we print "d" and not "d()"
Node opn = n.getOperator();
if (!t.isDatatype())
{
- toStream(op, opn, depth, false);
+ toStreamNode(op, opn, depth, false, lbind);
}
else if (t.isTuple() || t.isRecord())
{
- toStream(out, n[0], depth, true);
+ toStreamNode(out, n[0], depth, true, lbind);
out << '.';
const DType& dt = t.getDType();
if (t.isTuple())
}
else
{
- toStream(out, opn, depth, false);
+ toStreamNode(out, opn, depth, false, lbind);
}
return;
}else{
- toStream(op, opn, depth, false);
+ toStreamNode(op, opn, depth, false, lbind);
}
}
break;
op << "is_";
unsigned cindex = DType::indexOf(n.getOperator());
const DType& dt = DType::datatypeOf(n.getOperator());
- toStream(op, dt[cindex].getConstructor(), depth, false);
+ toStreamNode(op, dt[cindex].getConstructor(), depth, false, lbind);
}
break;
case kind::CONSTRUCTOR_TYPE:
if(i > 0) {
out << ", ";
}
- toStream(out, n[i], depth, false);
+ toStreamNode(out, n[i], depth, false, lbind);
}
if(n.getNumChildren() > 2) {
out << ')';
}
out << " -> ";
}
- toStream(out, n[n.getNumChildren() - 1], depth, false);
+ toStreamNode(out, n[n.getNumChildren() - 1], depth, false, lbind);
return;
case kind::TESTER_TYPE:
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << " -> BOOLEAN";
return;
break;
case kind::TUPLE_UPDATE:
- toStream(out, n[0], depth, true);
+ toStreamNode(out, n[0], depth, true, lbind);
out << " WITH ." << n.getOperator().getConst<TupleUpdate>().getIndex() << " := ";
- toStream(out, n[1], depth, true);
+ toStreamNode(out, n[1], depth, true, lbind);
return;
break;
case kind::RECORD_UPDATE:
- toStream(out, n[0], depth, true);
+ toStreamNode(out, n[0], depth, true, lbind);
out << " WITH ." << n.getOperator().getConst<RecordUpdate>().getField() << " := ";
- toStream(out, n[1], depth, true);
+ toStreamNode(out, n[1], depth, true, lbind);
return;
break;
// ARRAYS
case kind::ARRAY_TYPE:
out << "ARRAY ";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << " OF ";
- toStream(out, n[1], depth, false);
+ toStreamNode(out, n[1], depth, false, lbind);
return;
break;
case kind::SELECT:
- toStream(out, n[0], depth, true);
+ toStreamNode(out, n[0], depth, true, lbind);
out << '[';
- toStream(out, n[1], depth, false);
+ toStreamNode(out, n[1], depth, false, lbind);
out << ']';
return;
break;
out << '(';
}
TNode x = stk.top();
- toStream(out, x[0], depth, false);
+ toStreamNode(out, x[0], depth, false, lbind);
out << " WITH [";
- toStream(out, x[1], depth, false);
+ toStreamNode(out, x[1], depth, false, lbind);
out << "] := ";
- toStream(out, x[2], depth, false);
+ toStreamNode(out, x[2], depth, false, lbind);
stk.pop();
while(!stk.empty()) {
x = stk.top();
out << ", [";
- toStream(out, x[1], depth, false);
+ toStreamNode(out, x[1], depth, false, lbind);
out << "] := ";
- toStream(out, x[2], depth, false);
+ toStreamNode(out, x[2], depth, false, lbind);
stk.pop();
}
if (bracket) {
else
{
// ignore, there is no to-real in CVC language
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
}
return;
}
case kind::DIVISIBLE:
out << "DIVISIBLE(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ", " << n.getOperator().getConst<Divisible>().k << ")";
return;
out << "BVPLUS(";
out << BitVectorType(n.getType().toType()).getSize();
out << ',';
- toStream(out, n[child], depth, false);
+ toStreamNode(out, n[child], depth, false, lbind);
out << ',';
++child;
}
out << "BVPLUS(";
out << BitVectorType(n.getType().toType()).getSize();
out << ',';
- toStream(out, n[child], depth, false);
+ toStreamNode(out, n[child], depth, false, lbind);
out << ',';
- toStream(out, n[child + 1], depth, false);
+ toStreamNode(out, n[child + 1], depth, false, lbind);
while (child > 0) {
out << ')';
--child;
Assert(n.getType().isBitVector());
out << BitVectorType(n.getType().toType()).getSize();
out << ',';
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ',';
- toStream(out, n[1], depth, false);
+ toStreamNode(out, n[1], depth, false, lbind);
out << ')';
return;
break;
out << "BVMULT(";
out << BitVectorType(n.getType().toType()).getSize();
out << ',';
- toStream(out, n[child], depth, false);
+ toStreamNode(out, n[child], depth, false, lbind);
out << ',';
++child;
}
out << "BVMULT(";
out << BitVectorType(n.getType().toType()).getSize();
out << ',';
- toStream(out, n[child], depth, false);
+ toStreamNode(out, n[child], depth, false, lbind);
out << ',';
- toStream(out, n[child + 1], depth, false);
+ toStreamNode(out, n[child + 1], depth, false, lbind);
while (child > 0) {
out << ')';
--child;
break;
case kind::BITVECTOR_REPEAT:
out << "BVREPEAT(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ", " << n.getOperator().getConst<BitVectorRepeat>() << ')';
return;
break;
case kind::BITVECTOR_ZERO_EXTEND:
out << "BVZEROEXTEND(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ", " << n.getOperator().getConst<BitVectorZeroExtend>() << ')';
return;
break;
case kind::BITVECTOR_SIGN_EXTEND:
out << "SX(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ", " << BitVectorType(n.getType().toType()).getSize() << ')';
return;
break;
case kind::BITVECTOR_ROTATE_LEFT:
out << "BVROTL(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ", " << n.getOperator().getConst<BitVectorRotateLeft>() << ')';
return;
break;
case kind::BITVECTOR_ROTATE_RIGHT:
out << "BVROTR(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ", " << n.getOperator().getConst<BitVectorRotateRight>() << ')';
return;
break;
// SETS
case kind::SET_TYPE:
out << "SET OF ";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
return;
break;
case kind::UNION:
break;
case kind::SINGLETON:
out << "{";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << "}";
return;
break;
}
out << '{';
size_t i = 0;
- toStream(out, n[i++], depth, false);
+ toStreamNode(out, n[i++], depth, false, lbind);
for(;i+1 < n.getNumChildren(); ++i) {
out << ", ";
- toStream(out, n[i], depth, false);
+ toStreamNode(out, n[i], depth, false, lbind);
}
out << "} | ";
- toStream(out, n[i], depth, true);
+ toStreamNode(out, n[i], depth, true, lbind);
if(bracket) {
out << ')';
}
}
case kind::CARD: {
out << "CARD(";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, false, lbind);
out << ")";
return;
break;
// Quantifiers
case kind::FORALL:
out << "(FORALL";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, true, lbind);
out << " : ";
- toStream(out, n[1], depth, false);
+ toStreamNodeWithLetify(out, n[1], depth, true, lbind);
out << ')';
// TODO: user patterns?
return;
case kind::EXISTS:
out << "(EXISTS";
- toStream(out, n[0], depth, false);
+ toStreamNode(out, n[0], depth, true, lbind);
out << " : ";
- toStream(out, n[1], depth, false);
+ toStreamNodeWithLetify(out, n[1], depth, true, lbind);
out << ')';
// TODO: user patterns?
return;
if(i > 0) {
out << ", ";
}
- toStream(out, n[i], -1, false);
+ toStreamNode(out, n[i], -1, false, lbind);
out << ":";
n[i].getType().toStream(out, language::output::LANG_CVC4);
}
out << ", ";
}
}
- toStream(out, n[i], depth, opType == INFIX);
+ toStreamNode(out, n[i], depth, opType == INFIX, lbind);
}
switch (opType) {
out << ')' << op.str();
break;
}
-
-}/* CvcPrinter::toStream(TNode) */
+}
template <class T>
static bool tryToStream(std::ostream& out, const Command* c, bool cvc3Mode);
return false;
}
+void CvcPrinter::toStreamNodeWithLetify(std::ostream& out,
+ Node n,
+ int toDepth,
+ bool bracket,
+ LetBinding* lbind) const
+{
+ if (lbind == nullptr)
+ {
+ toStreamNode(out, n, toDepth, bracket, nullptr);
+ return;
+ }
+ std::vector<Node> letList;
+ lbind->letify(n, letList);
+ if (!letList.empty())
+ {
+ std::map<Node, uint32_t>::const_iterator it;
+ out << "LET ";
+ bool first = true;
+ for (size_t i = 0, nlets = letList.size(); i < nlets; i++)
+ {
+ if (!first)
+ {
+ out << ", ";
+ }
+ else
+ {
+ first = false;
+ }
+ Node nl = letList[i];
+ uint32_t id = lbind->getId(nl);
+ out << "_let_" << id << " = ";
+ Node nlc = lbind->convert(nl, "_let_", false);
+ toStreamNode(out, nlc, toDepth, true, lbind);
+ }
+ out << " IN ";
+ }
+ Node nc = lbind->convert(n, "_let_");
+ // print the body, passing the lbind object
+ toStreamNode(out, nc, toDepth, bracket, lbind);
+ lbind->popScope();
+}
+
}/* CVC4::printer::cvc namespace */
}/* CVC4::printer namespace */
}/* CVC4 namespace */