1 /********************* */
2 /*! \file smt2_printer.cpp
4 ** Original author: Morgan Deters
5 ** Major contributors: Andrew Reynolds
6 ** Minor contributors (to current version): Dejan Jovanovic, Tim King, Liana Hadarean, Francois Bobot
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2013 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
12 ** \brief The pretty-printer interface for the SMT2 output language
14 ** The pretty-printer interface for the SMT2 output language.
17 #include "printer/smt2/smt2_printer.h"
24 #include "util/boolean_simplification.h"
25 #include "printer/dagification_visitor.h"
26 #include "util/node_visitor.h"
27 #include "theory/substitutions.h"
28 #include "util/language.h"
29 #include "smt/smt_engine.h"
30 #include "smt/options.h"
31 #include "expr/node_manager_attributes.h"
33 #include "theory/theory_model.h"
34 #include "theory/arrays/theory_arrays_rewriter.h"
42 static string
smtKindString(Kind k
) throw();
44 static void printBvParameterizedOp(std::ostream
& out
, TNode n
) throw();
46 void Smt2Printer::toStream(std::ostream
& out
, TNode n
,
47 int toDepth
, bool types
, size_t dag
) const throw() {
49 DagificationVisitor
dv(dag
);
50 NodeVisitor
<DagificationVisitor
> visitor
;
52 const theory::SubstitutionMap
& lets
= dv
.getLets();
54 theory::SubstitutionMap::const_iterator i
= lets
.begin();
55 theory::SubstitutionMap::const_iterator i_end
= lets
.end();
56 for(; i
!= i_end
; ++ i
) {
58 toStream(out
, (*i
).second
, toDepth
, types
);
60 toStream(out
, (*i
).first
, toDepth
, types
);
64 Node body
= dv
.getDagifiedBody();
65 toStream(out
, body
, toDepth
, types
);
67 theory::SubstitutionMap::const_iterator i
= lets
.begin();
68 theory::SubstitutionMap::const_iterator i_end
= lets
.end();
69 for(; i
!= i_end
; ++ i
) {
74 toStream(out
, n
, toDepth
, types
);
78 static std::string
maybeQuoteSymbol(const std::string
& s
) {
79 // this is the set of SMT-LIBv2 permitted characters in "simple" (non-quoted) symbols
80 if(s
.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@$%^&*_-+=<>.?/") != string::npos
) {
83 ss
<< '|' << s
<< '|';
89 void Smt2Printer::toStream(std::ostream
& out
, TNode n
,
90 int toDepth
, bool types
) const throw() {
92 if(n
.getKind() == kind::NULL_EXPR
) {
100 if(n
.getAttribute(expr::VarNameAttr(), s
)) {
101 out
<< maybeQuoteSymbol(s
);
103 if(n
.getKind() == kind::VARIABLE
) {
106 out
<< n
.getKind() << '_';
111 // print the whole type, but not *its* type
113 n
.getType().toStream(out
, language::output::LANG_SMTLIB_V2
);
120 if(n
.getMetaKind() == kind::metakind::CONSTANT
) {
121 switch(n
.getKind()) {
122 case kind::TYPE_CONSTANT
:
123 switch(n
.getConst
<TypeConstant
>()) {
124 case BOOLEAN_TYPE
: out
<< "Bool"; break;
125 case REAL_TYPE
: out
<< "Real"; break;
126 case INTEGER_TYPE
: out
<< "Int"; break;
128 // fall back on whatever operator<< does on underlying type; we
129 // might luck out and be SMT-LIB v2 compliant
130 kind::metakind::NodeValueConstPrinter::toStream(out
, n
);
133 case kind::BITVECTOR_TYPE
:
134 out
<< "(_ BitVec " << n
.getConst
<BitVectorSize
>().size
<< ")";
136 case kind::CONST_BITVECTOR
: {
137 const BitVector
& bv
= n
.getConst
<BitVector
>();
138 const Integer
& x
= bv
.getValue();
139 unsigned n
= bv
.getSize();
141 out
<< "bv" << x
<<" " << n
;
146 // out << (x.testBit(n) ? '1' : '0');
150 case kind::CONST_BOOLEAN
:
151 // the default would print "1" or "0" for bool, that's not correct
153 out
<< (n
.getConst
<bool>() ? "true" : "false");
156 out
<< smtKindString(n
.getConst
<Kind
>());
158 case kind::CONST_RATIONAL
: {
159 Rational r
= n
.getConst
<Rational
>();
162 out
<< "(- " << -r
<< ')';
164 out
<< "(- (/ " << (-r
).getNumerator() << ' ' << (-r
).getDenominator() << "))";
170 out
<< "(/ " << r
.getNumerator() << ' ' << r
.getDenominator() << ')';
176 case kind::STORE_ALL
: {
177 ArrayStoreAll asa
= n
.getConst
<ArrayStoreAll
>();
178 out
<< "(__array_store_all__ " << asa
.getType() << " " << asa
.getExpr() << ")";
182 case kind::SUBRANGE_TYPE
: {
183 const SubrangeBounds
& bounds
= n
.getConst
<SubrangeBounds
>();
184 // No way to represent subranges in SMT-LIBv2; this is inspired
185 // by yices format (but isn't identical to it).
186 out
<< "(subrange " << bounds
.lower
<< ' ' << bounds
.upper
<< ')';
189 case kind::SUBTYPE_TYPE
:
190 // No way to represent predicate subtypes in SMT-LIBv2; this is
191 // inspired by yices format (but isn't identical to it).
192 out
<< "(subtype " << n
.getConst
<Predicate
>() << ')';
195 case kind::DATATYPE_TYPE
:
196 out
<< maybeQuoteSymbol(n
.getConst
<Datatype
>().getName());
199 case kind::UNINTERPRETED_CONSTANT
: {
200 const UninterpretedConstant
& uc
= n
.getConst
<UninterpretedConstant
>();
206 // fall back on whatever operator<< does on underlying type; we
207 // might luck out and be SMT-LIB v2 compliant
208 kind::metakind::NodeValueConstPrinter::toStream(out
, n
);
214 if(n
.getKind() == kind::SORT_TYPE
) {
216 if(n
.getAttribute(expr::VarNameAttr(), name
)) {
217 out
<< maybeQuoteSymbol(name
);
222 bool stillNeedToPrintParams
= true;
224 if(n
.getNumChildren() != 0 && n
.getKind()!=kind::INST_PATTERN_LIST
) out
<< '(';
225 switch(Kind k
= n
.getKind()) {
227 case kind::APPLY
: break;
229 case kind::DISTINCT
: out
<< smtKindString(k
) << " "; break;
230 case kind::CHAIN
: break;
231 case kind::TUPLE
: break;
232 case kind::SEXPR
: break;
241 case kind::ITE
: out
<< smtKindString(k
) << " "; break;
244 case kind::APPLY_UF
: break;
256 case kind::DIVISION_TOTAL
:
257 case kind::INTS_DIVISION
:
258 case kind::INTS_DIVISION_TOTAL
:
259 case kind::INTS_MODULUS
:
260 case kind::INTS_MODULUS_TOTAL
:
262 case kind::IS_INTEGER
:
263 case kind::TO_INTEGER
:
264 case kind::TO_REAL
: out
<< smtKindString(k
) << " "; break;
266 case kind::DIVISIBLE
:
267 out
<< "(_ divisible " << n
.getOperator().getConst
<Divisible
>().k
<< ")";
268 stillNeedToPrintParams
= false;
274 case kind::ARRAY_TYPE
: out
<< smtKindString(k
) << " "; break;
277 case kind::STRING_CONCAT
: out
<< "str.++ "; break;
278 case kind::STRING_IN_REGEXP
: out
<< "str.in.re "; break;
279 case kind::STRING_LENGTH
: out
<< "str.len "; break;
280 case kind::STRING_SUBSTR
: out
<< "str.substr "; break;
281 case kind::STRING_STRCTN
: out
<< "str.contain "; break;
282 case kind::STRING_CHARAT
: out
<< "str.at "; break;
283 case kind::STRING_STRIDOF
: out
<< "str.indexof "; break;
284 case kind::STRING_STRREPL
: out
<< "str.replace "; break;
285 case kind::STRING_TO_REGEXP
: out
<< "str.to.re "; break;
286 case kind::REGEXP_CONCAT
: out
<< "re.++ "; break;
287 case kind::REGEXP_OR
: out
<< "re.or "; break;
288 case kind::REGEXP_INTER
: out
<< "re.itr "; break;
289 case kind::REGEXP_STAR
: out
<< "re.* "; break;
290 case kind::REGEXP_PLUS
: out
<< "re.+ "; break;
291 case kind::REGEXP_OPT
: out
<< "re.opt "; break;
292 case kind::REGEXP_RANGE
: out
<< "re.range "; break;
295 case kind::BITVECTOR_CONCAT
: out
<< "concat "; break;
296 case kind::BITVECTOR_AND
: out
<< "bvand "; break;
297 case kind::BITVECTOR_OR
: out
<< "bvor "; break;
298 case kind::BITVECTOR_XOR
: out
<< "bvxor "; break;
299 case kind::BITVECTOR_NOT
: out
<< "bvnot "; break;
300 case kind::BITVECTOR_NAND
: out
<< "bvnand "; break;
301 case kind::BITVECTOR_NOR
: out
<< "bvnor "; break;
302 case kind::BITVECTOR_XNOR
: out
<< "bvxnor "; break;
303 case kind::BITVECTOR_COMP
: out
<< "bvcomp "; break;
304 case kind::BITVECTOR_MULT
: out
<< "bvmul "; break;
305 case kind::BITVECTOR_PLUS
: out
<< "bvadd "; break;
306 case kind::BITVECTOR_SUB
: out
<< "bvsub "; break;
307 case kind::BITVECTOR_NEG
: out
<< "bvneg "; break;
308 case kind::BITVECTOR_UDIV
: out
<< "bvudiv "; break;
309 case kind::BITVECTOR_UDIV_TOTAL
: out
<< "bvudiv_total "; break;
310 case kind::BITVECTOR_UREM
: out
<< "bvurem "; break;
311 case kind::BITVECTOR_UREM_TOTAL
: out
<< "bvurem_total "; break;
312 case kind::BITVECTOR_SDIV
: out
<< "bvsdiv "; break;
313 case kind::BITVECTOR_SREM
: out
<< "bvsrem "; break;
314 case kind::BITVECTOR_SMOD
: out
<< "bvsmod "; break;
315 case kind::BITVECTOR_SHL
: out
<< "bvshl "; break;
316 case kind::BITVECTOR_LSHR
: out
<< "bvlshr "; break;
317 case kind::BITVECTOR_ASHR
: out
<< "bvashr "; break;
318 case kind::BITVECTOR_ULT
: out
<< "bvult "; break;
319 case kind::BITVECTOR_ULE
: out
<< "bvule "; break;
320 case kind::BITVECTOR_UGT
: out
<< "bvugt "; break;
321 case kind::BITVECTOR_UGE
: out
<< "bvuge "; break;
322 case kind::BITVECTOR_SLT
: out
<< "bvslt "; break;
323 case kind::BITVECTOR_SLE
: out
<< "bvsle "; break;
324 case kind::BITVECTOR_SGT
: out
<< "bvsgt "; break;
325 case kind::BITVECTOR_SGE
: out
<< "bvsge "; break;
326 case kind::BITVECTOR_TO_NAT
: out
<< "bv2nat "; break;
328 case kind::BITVECTOR_EXTRACT
:
329 case kind::BITVECTOR_REPEAT
:
330 case kind::BITVECTOR_ZERO_EXTEND
:
331 case kind::BITVECTOR_SIGN_EXTEND
:
332 case kind::BITVECTOR_ROTATE_LEFT
:
333 case kind::BITVECTOR_ROTATE_RIGHT
:
334 case kind::INT_TO_BITVECTOR
:
335 printBvParameterizedOp(out
, n
);
337 stillNeedToPrintParams
= false;
341 case kind::APPLY_TYPE_ASCRIPTION
: {
343 toStream(out
, n
[0], toDepth
< 0 ? toDepth
: toDepth
- 1, types
);
345 TypeNode t
= TypeNode::fromType(n
.getOperator().getConst
<AscriptionType
>().getType());
346 out
<< (t
.isFunctionLike() ? t
.getRangeType() : t
);
351 case kind::APPLY_TESTER
:
352 case kind::APPLY_CONSTRUCTOR
:
353 case kind::APPLY_SELECTOR
:
354 case kind::PARAMETRIC_DATATYPE
:
360 if( k
==kind::FORALL
){
365 for( unsigned i
=0; i
<2; i
++) {
367 if( i
==0 && n
.getNumChildren()==3 ){
371 if( n
.getNumChildren()==3 ){
378 case kind::BOUND_VAR_LIST
:
379 // the left parenthesis is already printed (before the switch)
380 for(TNode::iterator i
= n
.begin(), iend
= n
.end();
383 toStream(out
, (*i
), toDepth
< 0 ? toDepth
: toDepth
- 1, types
);
385 out
<< (*i
).getType();
386 // The following code do stange things
387 // (*i).getType().toStream(out, toDepth < 0 ? toDepth : toDepth - 1,
388 // false, language::output::LANG_SMTLIB_V2);
396 case kind::INST_PATTERN
:
398 case kind::INST_PATTERN_LIST
:
399 // TODO user patterns
400 for(unsigned i
=0; i
<n
.getNumChildren(); i
++) {
401 out
<< ":pattern " << n
[i
];
407 // fall back on however the kind prints itself; this probably
408 // won't be SMT-LIB v2 compliant, but it will be clear from the
409 // output that support for the kind needs to be added here.
410 out
<< n
.getKind() << ' ';
412 if( n
.getMetaKind() == kind::metakind::PARAMETERIZED
&&
413 stillNeedToPrintParams
) {
415 toStream(out
, n
.getOperator(), toDepth
< 0 ? toDepth
: toDepth
- 1, types
);
419 if(n
.getNumChildren() > 0) {
423 for(TNode::iterator i
= n
.begin(),
427 toStream(out
, *i
, toDepth
< 0 ? toDepth
: toDepth
- 1, types
);
435 if(n
.getNumChildren() != 0) {
438 }/* Smt2Printer::toStream(TNode) */
440 static string
smtKindString(Kind k
) throw() {
443 case kind::APPLY
: break;
444 case kind::EQUAL
: return "=";
445 case kind::DISTINCT
: return "distinct";
446 case kind::CHAIN
: break;
447 case kind::TUPLE
: break;
448 case kind::SEXPR
: break;
451 case kind::NOT
: return "not";
452 case kind::AND
: return "and";
453 case kind::IFF
: return "=";
454 case kind::IMPLIES
: return "=>";
455 case kind::OR
: return "or";
456 case kind::XOR
: return "xor";
457 case kind::ITE
: return "ite";
460 case kind::APPLY_UF
: break;
463 case kind::PLUS
: return "+";
464 case kind::MULT
: return "*";
465 case kind::MINUS
: return "-";
466 case kind::UMINUS
: return "-";
467 case kind::LT
: return "<";
468 case kind::LEQ
: return "<=";
469 case kind::GT
: return ">";
470 case kind::GEQ
: return ">=";
472 case kind::DIVISION_TOTAL
: return "/";
473 case kind::INTS_DIVISION
: return "div";
474 case kind::INTS_DIVISION_TOTAL
: return "INTS_DIVISION_TOTAL";
475 case kind::INTS_MODULUS
: return "mod";
476 case kind::INTS_MODULUS_TOTAL
: return "INTS_MODULUS_TOTAL";
477 case kind::ABS
: return "abs";
478 case kind::IS_INTEGER
: return "is_int";
479 case kind::TO_INTEGER
: return "to_int";
480 case kind::TO_REAL
: return "to_real";
483 case kind::SELECT
: return "select";
484 case kind::STORE
: return "store";
485 case kind::STORE_ALL
: return "__array_store_all__";
486 case kind::ARRAY_TYPE
: return "Array";
489 case kind::BITVECTOR_CONCAT
: return "concat";
490 case kind::BITVECTOR_AND
: return "bvand";
491 case kind::BITVECTOR_OR
: return "bvor";
492 case kind::BITVECTOR_XOR
: return "bvxor";
493 case kind::BITVECTOR_NOT
: return "bvnot";
494 case kind::BITVECTOR_NAND
: return "bvnand";
495 case kind::BITVECTOR_NOR
: return "bvnor";
496 case kind::BITVECTOR_XNOR
: return "bvxnor";
497 case kind::BITVECTOR_COMP
: return "bvcomp";
498 case kind::BITVECTOR_MULT
: return "bvmul";
499 case kind::BITVECTOR_PLUS
: return "bvadd";
500 case kind::BITVECTOR_SUB
: return "bvsub";
501 case kind::BITVECTOR_NEG
: return "bvneg";
502 case kind::BITVECTOR_UDIV
: return "bvudiv";
503 case kind::BITVECTOR_UREM
: return "bvurem";
504 case kind::BITVECTOR_SDIV
: return "bvsdiv";
505 case kind::BITVECTOR_SREM
: return "bvsrem";
506 case kind::BITVECTOR_SMOD
: return "bvsmod";
507 case kind::BITVECTOR_SHL
: return "bvshl";
508 case kind::BITVECTOR_LSHR
: return "bvlshr";
509 case kind::BITVECTOR_ASHR
: return "bvashr";
510 case kind::BITVECTOR_ULT
: return "bvult";
511 case kind::BITVECTOR_ULE
: return "bvule";
512 case kind::BITVECTOR_UGT
: return "bvugt";
513 case kind::BITVECTOR_UGE
: return "bvuge";
514 case kind::BITVECTOR_SLT
: return "bvslt";
515 case kind::BITVECTOR_SLE
: return "bvsle";
516 case kind::BITVECTOR_SGT
: return "bvsgt";
517 case kind::BITVECTOR_SGE
: return "bvsge";
519 case kind::BITVECTOR_EXTRACT
: return "extract";
520 case kind::BITVECTOR_REPEAT
: return "repeat";
521 case kind::BITVECTOR_ZERO_EXTEND
: return "zero_extend";
522 case kind::BITVECTOR_SIGN_EXTEND
: return "sign_extend";
523 case kind::BITVECTOR_ROTATE_LEFT
: return "rotate_left";
524 case kind::BITVECTOR_ROTATE_RIGHT
: return "rotate_right";
529 // no SMT way to print these
530 return kind::kindToString(k
);
533 static void printBvParameterizedOp(std::ostream
& out
, TNode n
) throw() {
535 switch(n
.getKind()) {
536 case kind::BITVECTOR_EXTRACT
: {
537 BitVectorExtract p
= n
.getOperator().getConst
<BitVectorExtract
>();
538 out
<< "extract " << p
.high
<< ' ' << p
.low
;
541 case kind::BITVECTOR_REPEAT
:
543 << n
.getOperator().getConst
<BitVectorRepeat
>().repeatAmount
;
545 case kind::BITVECTOR_ZERO_EXTEND
:
546 out
<< "zero_extend "
547 << n
.getOperator().getConst
<BitVectorZeroExtend
>().zeroExtendAmount
;
549 case kind::BITVECTOR_SIGN_EXTEND
:
550 out
<< "sign_extend "
551 << n
.getOperator().getConst
<BitVectorSignExtend
>().signExtendAmount
;
553 case kind::BITVECTOR_ROTATE_LEFT
:
554 out
<< "rotate_left "
555 << n
.getOperator().getConst
<BitVectorRotateLeft
>().rotateLeftAmount
;
557 case kind::BITVECTOR_ROTATE_RIGHT
:
558 out
<< "rotate_right "
559 << n
.getOperator().getConst
<BitVectorRotateRight
>().rotateRightAmount
;
561 case kind::INT_TO_BITVECTOR
:
563 << n
.getOperator().getConst
<IntToBitVector
>().size
;
572 static bool tryToStream(std::ostream
& out
, const Command
* c
) throw();
574 void Smt2Printer::toStream(std::ostream
& out
, const Command
* c
,
575 int toDepth
, bool types
, size_t dag
) const throw() {
576 expr::ExprSetDepth::Scope
sdScope(out
, toDepth
);
577 expr::ExprPrintTypes::Scope
ptScope(out
, types
);
578 expr::ExprDag::Scope
dagScope(out
, dag
);
580 if(tryToStream
<AssertCommand
>(out
, c
) ||
581 tryToStream
<PushCommand
>(out
, c
) ||
582 tryToStream
<PopCommand
>(out
, c
) ||
583 tryToStream
<CheckSatCommand
>(out
, c
) ||
584 tryToStream
<QueryCommand
>(out
, c
) ||
585 tryToStream
<QuitCommand
>(out
, c
) ||
586 tryToStream
<DeclarationSequence
>(out
, c
) ||
587 tryToStream
<CommandSequence
>(out
, c
) ||
588 tryToStream
<DeclareFunctionCommand
>(out
, c
) ||
589 tryToStream
<DeclareTypeCommand
>(out
, c
) ||
590 tryToStream
<DefineTypeCommand
>(out
, c
) ||
591 tryToStream
<DefineNamedFunctionCommand
>(out
, c
) ||
592 tryToStream
<DefineFunctionCommand
>(out
, c
) ||
593 tryToStream
<SimplifyCommand
>(out
, c
) ||
594 tryToStream
<GetValueCommand
>(out
, c
) ||
595 tryToStream
<GetModelCommand
>(out
, c
) ||
596 tryToStream
<GetAssignmentCommand
>(out
, c
) ||
597 tryToStream
<GetAssertionsCommand
>(out
, c
) ||
598 tryToStream
<GetProofCommand
>(out
, c
) ||
599 tryToStream
<SetBenchmarkStatusCommand
>(out
, c
) ||
600 tryToStream
<SetBenchmarkLogicCommand
>(out
, c
) ||
601 tryToStream
<SetInfoCommand
>(out
, c
) ||
602 tryToStream
<GetInfoCommand
>(out
, c
) ||
603 tryToStream
<SetOptionCommand
>(out
, c
) ||
604 tryToStream
<GetOptionCommand
>(out
, c
) ||
605 tryToStream
<DatatypeDeclarationCommand
>(out
, c
) ||
606 tryToStream
<CommentCommand
>(out
, c
) ||
607 tryToStream
<EmptyCommand
>(out
, c
) ||
608 tryToStream
<EchoCommand
>(out
, c
)) {
612 out
<< "ERROR: don't know how to print a Command of class: "
613 << typeid(*c
).name() << endl
;
615 }/* Smt2Printer::toStream(Command*) */
617 static inline void toStream(std::ostream
& out
, const SExpr
& sexpr
) throw() {
618 Printer::getPrinter(language::output::LANG_SMTLIB_V2
)->toStream(out
, sexpr
);
622 static bool tryToStream(std::ostream
& out
, const CommandStatus
* s
) throw();
624 void Smt2Printer::toStream(std::ostream
& out
, const CommandStatus
* s
) const throw() {
626 if(tryToStream
<CommandSuccess
>(out
, s
) ||
627 tryToStream
<CommandFailure
>(out
, s
) ||
628 tryToStream
<CommandUnsupported
>(out
, s
)) {
632 out
<< "ERROR: don't know how to print a CommandStatus of class: "
633 << typeid(*s
).name() << endl
;
635 }/* Smt2Printer::toStream(CommandStatus*) */
638 void Smt2Printer::toStream(std::ostream
& out
, const Model
& m
) const throw() {
639 out
<< "(model" << std::endl
;
640 this->Printer::toStream(out
, m
);
641 out
<< ")" << std::endl
;
645 void Smt2Printer::toStream(std::ostream
& out
, const Model
& m
, const Command
* c
) const throw() {
646 const theory::TheoryModel
& tm
= (const theory::TheoryModel
&) m
;
647 if(dynamic_cast<const DeclareTypeCommand
*>(c
) != NULL
) {
648 TypeNode tn
= TypeNode::fromType( ((const DeclareTypeCommand
*)c
)->getType() );
649 if( options::modelUninterpDtEnum() && tn
.isSort() &&
650 tm
.d_rep_set
.d_type_reps
.find( tn
)!=tm
.d_rep_set
.d_type_reps
.end() ){
651 out
<< "(declare-datatypes () ((" << dynamic_cast<const DeclareTypeCommand
*>(c
)->getSymbol() << " ";
652 for( size_t i
=0; i
<(*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
.size(); i
++ ){
653 out
<< "(" << (*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
[i
] << ")";
655 out
<< ")))" << std::endl
;
658 //print the cardinality
659 if( tm
.d_rep_set
.d_type_reps
.find( tn
)!=tm
.d_rep_set
.d_type_reps
.end() ){
660 out
<< "; cardinality of " << tn
<< " is " << (*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
.size() << std::endl
;
663 out
<< c
<< std::endl
;
665 //print the representatives
666 if( tm
.d_rep_set
.d_type_reps
.find( tn
)!=tm
.d_rep_set
.d_type_reps
.end() ){
667 for( size_t i
=0; i
<(*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
.size(); i
++ ){
668 if( (*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
[i
].isVar() ){
669 out
<< "(declare-fun " << (*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
[i
] << " () " << tn
<< ")" << std::endl
;
671 out
<< "; rep: " << (*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
[i
] << std::endl
;
677 } else if(dynamic_cast<const DeclareFunctionCommand
*>(c
) != NULL
) {
678 Node n
= Node::fromExpr( ((const DeclareFunctionCommand
*)c
)->getFunction() );
679 if(n
.getKind() == kind::SKOLEM
) {
680 // don't print out internal stuff
683 Node val
= Node::fromExpr(tm
.getSmtEngine()->getValue(n
.toExpr()));
684 if(val
.getKind() == kind::LAMBDA
) {
685 out
<< "(define-fun " << n
<< " " << val
[0]
686 << " " << n
.getType().getRangeType()
687 << " " << val
[1] << ")" << std::endl
;
689 if( options::modelUninterpDtEnum() && val
.getKind() == kind::STORE
) {
690 TypeNode tn
= val
[1].getType();
691 if (tn
.isSort() && tm
.d_rep_set
.d_type_reps
.find( tn
)!=tm
.d_rep_set
.d_type_reps
.end() ){
692 Cardinality
indexCard((*tm
.d_rep_set
.d_type_reps
.find(tn
)).second
.size());
693 val
= theory::arrays::TheoryArraysRewriter::normalizeConstant( val
, indexCard
);
696 out
<< "(define-fun " << n
<< " () "
697 << n
.getType() << " " << val
<< ")" << std::endl
;
700 //for table format (work in progress)
701 bool printedModel = false;
702 if( tn.isFunction() ){
703 if( options::modelFormatMode()==MODEL_FORMAT_MODE_TABLE ){
704 //specialized table format for functions
705 RepSetIterator riter( &d_rep_set );
706 riter.setFunctionDomain( n );
707 while( !riter.isFinished() ){
708 std::vector< Node > children;
709 children.push_back( n );
710 for( int i=0; i<riter.getNumTerms(); i++ ){
711 children.push_back( riter.getTerm( i ) );
713 Node nn = NodeManager::currentNM()->mkNode( APPLY_UF, children );
714 Node val = getValue( nn );
723 out
<< c
<< std::endl
;
727 void Smt2Printer::toStream(std::ostream
& out
, const Result
& r
) const throw() {
728 if(r
.getType() == Result::TYPE_SAT
&& r
.isSat() == Result::SAT_UNKNOWN
) {
731 Printer::toStream(out
, r
);
735 static void toStream(std::ostream
& out
, const AssertCommand
* c
) throw() {
736 out
<< "(assert " << c
->getExpr() << ")";
739 static void toStream(std::ostream
& out
, const PushCommand
* c
) throw() {
743 static void toStream(std::ostream
& out
, const PopCommand
* c
) throw() {
747 static void toStream(std::ostream
& out
, const CheckSatCommand
* c
) throw() {
748 Expr e
= c
->getExpr();
750 out
<< PushCommand() << endl
751 << AssertCommand(e
) << endl
752 << CheckSatCommand() << endl
753 << PopCommand() << endl
;
755 out
<< "(check-sat)";
759 static void toStream(std::ostream
& out
, const QueryCommand
* c
) throw() {
760 Expr e
= c
->getExpr();
762 out
<< PushCommand() << endl
763 << AssertCommand(BooleanSimplification::negate(e
)) << endl
764 << CheckSatCommand() << endl
765 << PopCommand() << endl
;
767 out
<< "(check-sat)";
771 static void toStream(std::ostream
& out
, const QuitCommand
* c
) throw() {
775 static void toStream(std::ostream
& out
, const CommandSequence
* c
) throw() {
776 for(CommandSequence::const_iterator i
= c
->begin();
783 static void toStream(std::ostream
& out
, const DeclareFunctionCommand
* c
) throw() {
784 Type type
= c
->getType();
785 out
<< "(declare-fun " << c
->getSymbol() << " (";
786 if(type
.isFunction()) {
787 FunctionType ft
= type
;
788 const vector
<Type
> argTypes
= ft
.getArgTypes();
789 if(argTypes
.size() > 0) {
790 copy( argTypes
.begin(), argTypes
.end() - 1,
791 ostream_iterator
<Type
>(out
, " ") );
792 out
<< argTypes
.back();
794 type
= ft
.getRangeType();
797 out
<< ") " << type
<< ")";
800 static void toStream(std::ostream
& out
, const DefineFunctionCommand
* c
) throw() {
801 Expr func
= c
->getFunction();
802 const vector
<Expr
>* formals
= &c
->getFormals();
803 out
<< "(define-fun " << func
<< " (";
804 Type type
= func
.getType();
805 Expr formula
= c
->getFormula();
806 if(type
.isFunction()) {
808 if(formals
->empty()) {
809 const vector
<Type
>& params
= FunctionType(type
).getArgTypes();
810 for(vector
<Type
>::const_iterator j
= params
.begin(); j
!= params
.end(); ++j
) {
811 f
.push_back(NodeManager::currentNM()->mkSkolem("a", TypeNode::fromType(*j
), "",
812 NodeManager::SKOLEM_NO_NOTIFY
).toExpr());
814 formula
= NodeManager::currentNM()->toExprManager()->mkExpr(kind::APPLY_UF
, formula
, f
);
817 vector
<Expr
>::const_iterator i
= formals
->begin();
819 out
<< "(" << (*i
) << " " << (*i
).getType() << ")";
821 if(i
!= formals
->end()) {
827 type
= FunctionType(type
).getRangeType();
829 out
<< ") " << type
<< " " << formula
<< ")";
832 static void toStream(std::ostream
& out
, const DeclareTypeCommand
* c
) throw() {
833 out
<< "(declare-sort " << c
->getSymbol() << " " << c
->getArity() << ")";
836 static void toStream(std::ostream
& out
, const DefineTypeCommand
* c
) throw() {
837 const vector
<Type
>& params
= c
->getParameters();
838 out
<< "(define-sort " << c
->getSymbol() << " (";
839 if(params
.size() > 0) {
840 copy( params
.begin(), params
.end() - 1,
841 ostream_iterator
<Type
>(out
, " ") );
842 out
<< params
.back();
844 out
<< ") " << c
->getType() << ")";
847 static void toStream(std::ostream
& out
, const DefineNamedFunctionCommand
* c
) throw() {
848 out
<< "DefineNamedFunction( ";
849 toStream(out
, static_cast<const DefineFunctionCommand
*>(c
));
852 out
<< "ERROR: don't know how to output define-named-function command" << endl
;
855 static void toStream(std::ostream
& out
, const SimplifyCommand
* c
) throw() {
856 out
<< "Simplify( << " << c
->getTerm() << " >> )";
858 out
<< "ERROR: don't know how to output simplify command" << endl
;
861 static void toStream(std::ostream
& out
, const GetValueCommand
* c
) throw() {
862 out
<< "(get-value ( ";
863 const vector
<Expr
>& terms
= c
->getTerms();
864 copy(terms
.begin(), terms
.end(), ostream_iterator
<Expr
>(out
, " "));
868 static void toStream(std::ostream
& out
, const GetModelCommand
* c
) throw() {
869 out
<< "(get-model)";
872 static void toStream(std::ostream
& out
, const GetAssignmentCommand
* c
) throw() {
873 out
<< "(get-assignment)";
876 static void toStream(std::ostream
& out
, const GetAssertionsCommand
* c
) throw() {
877 out
<< "(get-assertions)";
880 static void toStream(std::ostream
& out
, const GetProofCommand
* c
) throw() {
881 out
<< "(get-proof)";
884 static void toStream(std::ostream
& out
, const SetBenchmarkStatusCommand
* c
) throw() {
885 out
<< "(set-info :status " << c
->getStatus() << ")";
888 static void toStream(std::ostream
& out
, const SetBenchmarkLogicCommand
* c
) throw() {
889 out
<< "(set-logic " << c
->getLogic() << ")";
892 static void toStream(std::ostream
& out
, const SetInfoCommand
* c
) throw() {
893 out
<< "(set-info :" << c
->getFlag() << " ";
894 toStream(out
, c
->getSExpr());
898 static void toStream(std::ostream
& out
, const GetInfoCommand
* c
) throw() {
899 out
<< "(get-info :" << c
->getFlag() << ")";
902 static void toStream(std::ostream
& out
, const SetOptionCommand
* c
) throw() {
903 out
<< "(set-option :" << c
->getFlag() << " ";
904 toStream(out
, c
->getSExpr());
908 static void toStream(std::ostream
& out
, const GetOptionCommand
* c
) throw() {
909 out
<< "(get-option :" << c
->getFlag() << ")";
912 static void toStream(std::ostream
& out
, const DatatypeDeclarationCommand
* c
) throw() {
913 const vector
<DatatypeType
>& datatypes
= c
->getDatatypes();
914 out
<< "(declare-datatypes () (";
915 for(vector
<DatatypeType
>::const_iterator i
= datatypes
.begin(),
916 i_end
= datatypes
.end();
920 const Datatype
& d
= i
->getDatatype();
922 out
<< "(" << maybeQuoteSymbol(d
.getName()) << " ";
923 for(Datatype::const_iterator ctor
= d
.begin(), ctor_end
= d
.end();
924 ctor
!= ctor_end
; ++ctor
){
925 if( ctor
!=d
.begin() ) out
<< " ";
926 out
<< "(" << maybeQuoteSymbol(ctor
->getName());
928 for(DatatypeConstructor::const_iterator arg
= ctor
->begin(), arg_end
= ctor
->end();
929 arg
!= arg_end
; ++arg
){
930 out
<< " (" << arg
->getSelector() << " "
931 << static_cast<SelectorType
>(arg
->getType()).getRangeType() << ")";
940 static void toStream(std::ostream
& out
, const CommentCommand
* c
) throw() {
941 string s
= c
->getComment();
943 while((pos
= s
.find_first_of('"', pos
)) != string::npos
) {
944 s
.replace(pos
, 1, "\\\"");
947 out
<< "(set-info :notes \"" << s
<< "\")";
950 static void toStream(std::ostream
& out
, const EmptyCommand
* c
) throw() {
953 static void toStream(std::ostream
& out
, const EchoCommand
* c
) throw() {
954 out
<< "(echo \"" << c
->getOutput() << "\")";
958 static bool tryToStream(std::ostream
& out
, const Command
* c
) throw() {
959 if(typeid(*c
) == typeid(T
)) {
960 toStream(out
, dynamic_cast<const T
*>(c
));
966 static void toStream(std::ostream
& out
, const CommandSuccess
* s
) throw() {
967 if(Command::printsuccess::getPrintSuccess(out
)) {
968 out
<< "success" << endl
;
972 static void toStream(std::ostream
& out
, const CommandUnsupported
* s
) throw() {
973 #ifdef CVC4_COMPETITION_MODE
974 // if in competition mode, lie and say we're ok
975 // (we have nothing to lose by saying success, and everything to lose
976 // if we say "unsupported")
977 out
<< "success" << endl
;
978 #else /* CVC4_COMPETITION_MODE */
979 out
<< "unsupported" << endl
;
980 #endif /* CVC4_COMPETITION_MODE */
983 static void toStream(std::ostream
& out
, const CommandFailure
* s
) throw() {
984 string message
= s
->getMessage();
985 // escape all double-quotes
987 while((pos
= message
.find('"')) != string::npos
) {
988 message
= message
.replace(pos
, 1, "\\\"");
990 out
<< "(error \"" << message
<< "\")" << endl
;
994 static bool tryToStream(std::ostream
& out
, const CommandStatus
* s
) throw() {
995 if(typeid(*s
) == typeid(T
)) {
996 toStream(out
, dynamic_cast<const T
*>(s
));
1002 }/* CVC4::printer::smt2 namespace */
1003 }/* CVC4::printer namespace */
1004 }/* CVC4 namespace */