1 /********************* */
2 /*! \file ast_printer.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Morgan Deters, Tim King, Liana Hadarean
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
8 ** in the top-level source directory) and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
11 **
12 ** \brief The pretty-printer interface for the AST output language
13 **
14 ** The pretty-printer interface for the AST output language.
15 **/
16 #include "printer/ast/ast_printer.h"
17
18 #include <iostream>
19 #include <string>
20 #include <typeinfo>
21 #include <vector>
22
23 #include "expr/expr.h" // for ExprSetDepth etc..
24 #include "expr/node_manager_attributes.h" // for VarNameAttr
25 #include "options/language.h" // for LANG_AST
26 #include "printer/dagification_visitor.h"
27 #include "smt/command.h"
28 #include "smt_util/node_visitor.h"
29 #include "theory/substitutions.h"
30
31 using namespace std;
32
33 namespace CVC4 {
34 namespace printer {
35 namespace ast {
36
toStream(std::ostream & out,TNode n,int toDepth,bool types,size_t dag) const37 void AstPrinter::toStream(
38 std::ostream& out, TNode n, int toDepth, bool types, size_t dag) const
39 {
40 if(dag != 0) {
41 DagificationVisitor dv(dag);
42 NodeVisitor<DagificationVisitor> visitor;
43 visitor.run(dv, n);
44 const theory::SubstitutionMap& lets = dv.getLets();
45 if(!lets.empty()) {
46 out << "(LET ";
47 bool first = true;
48 for(theory::SubstitutionMap::const_iterator i = lets.begin();
49 i != lets.end();
50 ++i) {
51 if(! first) {
52 out << ", ";
53 } else {
54 first = false;
55 }
56 toStream(out, (*i).second, toDepth, types, false);
57 out << " := ";
58 toStream(out, (*i).first, toDepth, types, false);
59 }
60 out << " IN ";
61 }
62 Node body = dv.getDagifiedBody();
63 toStream(out, body, toDepth, types);
64 if(!lets.empty()) {
65 out << ')';
66 }
67 } else {
68 toStream(out, n, toDepth, types);
69 }
70 }
71
toStream(std::ostream & out,TNode n,int toDepth,bool types) const72 void AstPrinter::toStream(std::ostream& out,
73 TNode n,
74 int toDepth,
75 bool types) const
76 {
77 // null
78 if(n.getKind() == kind::NULL_EXPR) {
79 out << "null";
80 return;
81 }
82
83 // variable
84 if(n.getMetaKind() == kind::metakind::VARIABLE) {
85 string s;
86 if(n.getAttribute(expr::VarNameAttr(), s)) {
87 out << s;
88 } else {
89 out << "var_" << n.getId();
90 }
91 if(types) {
92 // print the whole type, but not *its* type
93 out << ":";
94 n.getType().toStream(out, language::output::LANG_AST);
95 }
96
97 return;
98 }
99
100 out << '(' << n.getKind();
101 if(n.getMetaKind() == kind::metakind::CONSTANT) {
102 // constant
103 out << ' ';
104 kind::metakind::NodeValueConstPrinter::toStream(out, n);
105 } else {
106 // operator
107 if(n.getMetaKind() == kind::metakind::PARAMETERIZED) {
108 out << ' ';
109 if(toDepth != 0) {
110 toStream(out, n.getOperator(), toDepth < 0 ? toDepth : toDepth - 1, types);
111 } else {
112 out << "(...)";
113 }
114 }
115 for(TNode::iterator i = n.begin(),
116 iend = n.end();
117 i != iend;
118 ++i) {
119 if(i != iend) {
120 out << ' ';
121 }
122 if(toDepth != 0) {
123 toStream(out, *i, toDepth < 0 ? toDepth : toDepth - 1, types);
124 } else {
125 out << "(...)";
126 }
127 }
128 }
129 out << ')';
130 }/* AstPrinter::toStream(TNode) */
131
132 template <class T>
133 static bool tryToStream(std::ostream& out, const Command* c);
134
toStream(std::ostream & out,const Command * c,int toDepth,bool types,size_t dag) const135 void AstPrinter::toStream(std::ostream& out,
136 const Command* c,
137 int toDepth,
138 bool types,
139 size_t dag) const
140 {
141 expr::ExprSetDepth::Scope sdScope(out, toDepth);
142 expr::ExprPrintTypes::Scope ptScope(out, types);
143 expr::ExprDag::Scope dagScope(out, dag);
144
145 if(tryToStream<EmptyCommand>(out, c) ||
146 tryToStream<AssertCommand>(out, c) ||
147 tryToStream<PushCommand>(out, c) ||
148 tryToStream<PopCommand>(out, c) ||
149 tryToStream<CheckSatCommand>(out, c) ||
150 tryToStream<CheckSatAssumingCommand>(out, c) ||
151 tryToStream<QueryCommand>(out, c) ||
152 tryToStream<ResetCommand>(out, c) ||
153 tryToStream<ResetAssertionsCommand>(out, c) ||
154 tryToStream<QuitCommand>(out, c) ||
155 tryToStream<DeclarationSequence>(out, c) ||
156 tryToStream<CommandSequence>(out, c) ||
157 tryToStream<DeclareFunctionCommand>(out, c) ||
158 tryToStream<DeclareTypeCommand>(out, c) ||
159 tryToStream<DefineTypeCommand>(out, c) ||
160 tryToStream<DefineNamedFunctionCommand>(out, c) ||
161 tryToStream<DefineFunctionCommand>(out, c) ||
162 tryToStream<SimplifyCommand>(out, c) ||
163 tryToStream<GetValueCommand>(out, c) ||
164 tryToStream<GetModelCommand>(out, c) ||
165 tryToStream<GetAssignmentCommand>(out, c) ||
166 tryToStream<GetAssertionsCommand>(out, c) ||
167 tryToStream<GetProofCommand>(out, c) ||
168 tryToStream<SetBenchmarkStatusCommand>(out, c) ||
169 tryToStream<SetBenchmarkLogicCommand>(out, c) ||
170 tryToStream<SetInfoCommand>(out, c) ||
171 tryToStream<GetInfoCommand>(out, c) ||
172 tryToStream<SetOptionCommand>(out, c) ||
173 tryToStream<GetOptionCommand>(out, c) ||
174 tryToStream<DatatypeDeclarationCommand>(out, c) ||
175 tryToStream<CommentCommand>(out, c)) {
176 return;
177 }
178
179 out << "ERROR: don't know how to print a Command of class: "
180 << typeid(*c).name() << endl;
181
182 }/* AstPrinter::toStream(Command*) */
183
184 template <class T>
185 static bool tryToStream(std::ostream& out, const CommandStatus* s);
186
toStream(std::ostream & out,const CommandStatus * s) const187 void AstPrinter::toStream(std::ostream& out, const CommandStatus* s) const
188 {
189 if(tryToStream<CommandSuccess>(out, s) ||
190 tryToStream<CommandFailure>(out, s) ||
191 tryToStream<CommandUnsupported>(out, s) ||
192 tryToStream<CommandInterrupted>(out, s)) {
193 return;
194 }
195
196 out << "ERROR: don't know how to print a CommandStatus of class: "
197 << typeid(*s).name() << endl;
198
199 }/* AstPrinter::toStream(CommandStatus*) */
200
toStream(std::ostream & out,const Model & m) const201 void AstPrinter::toStream(std::ostream& out, const Model& m) const
202 {
203 out << "Model()";
204 }
205
toStream(std::ostream & out,const Model & m,const Command * c) const206 void AstPrinter::toStream(std::ostream& out,
207 const Model& m,
208 const Command* c) const
209 {
210 // shouldn't be called; only the non-Command* version above should be
211 Unreachable();
212 }
213
toStream(std::ostream & out,const EmptyCommand * c)214 static void toStream(std::ostream& out, const EmptyCommand* c)
215 {
216 out << "EmptyCommand(" << c->getName() << ")";
217 }
218
toStream(std::ostream & out,const AssertCommand * c)219 static void toStream(std::ostream& out, const AssertCommand* c)
220 {
221 out << "Assert(" << c->getExpr() << ")";
222 }
223
toStream(std::ostream & out,const PushCommand * c)224 static void toStream(std::ostream& out, const PushCommand* c)
225 {
226 out << "Push()";
227 }
228
toStream(std::ostream & out,const PopCommand * c)229 static void toStream(std::ostream& out, const PopCommand* c) { out << "Pop()"; }
230
toStream(std::ostream & out,const CheckSatCommand * c)231 static void toStream(std::ostream& out, const CheckSatCommand* c)
232 {
233 Expr e = c->getExpr();
234 if(e.isNull()) {
235 out << "CheckSat()";
236 } else {
237 out << "CheckSat(" << e << ")";
238 }
239 }
240
toStream(std::ostream & out,const CheckSatAssumingCommand * c)241 static void toStream(std::ostream& out, const CheckSatAssumingCommand* c)
242 {
243 const vector<Expr>& terms = c->getTerms();
244 out << "CheckSatAssuming( << ";
245 copy(terms.begin(), terms.end(), ostream_iterator<Expr>(out, ", "));
246 out << ">> )";
247 }
248
toStream(std::ostream & out,const QueryCommand * c)249 static void toStream(std::ostream& out, const QueryCommand* c)
250 {
251 out << "Query(" << c->getExpr() << ')';
252 }
253
toStream(std::ostream & out,const ResetCommand * c)254 static void toStream(std::ostream& out, const ResetCommand* c)
255 {
256 out << "Reset()";
257 }
258
toStream(std::ostream & out,const ResetAssertionsCommand * c)259 static void toStream(std::ostream& out, const ResetAssertionsCommand* c)
260 {
261 out << "ResetAssertions()";
262 }
263
toStream(std::ostream & out,const QuitCommand * c)264 static void toStream(std::ostream& out, const QuitCommand* c)
265 {
266 out << "Quit()";
267 }
268
toStream(std::ostream & out,const DeclarationSequence * c)269 static void toStream(std::ostream& out, const DeclarationSequence* c)
270 {
271 out << "DeclarationSequence[" << endl;
272 for(CommandSequence::const_iterator i = c->begin();
273 i != c->end();
274 ++i) {
275 out << *i << endl;
276 }
277 out << "]";
278 }
279
toStream(std::ostream & out,const CommandSequence * c)280 static void toStream(std::ostream& out, const CommandSequence* c)
281 {
282 out << "CommandSequence[" << endl;
283 for(CommandSequence::const_iterator i = c->begin();
284 i != c->end();
285 ++i) {
286 out << *i << endl;
287 }
288 out << "]";
289 }
290
toStream(std::ostream & out,const DeclareFunctionCommand * c)291 static void toStream(std::ostream& out, const DeclareFunctionCommand* c)
292 {
293 out << "Declare(" << c->getSymbol() << "," << c->getType() << ")";
294 }
295
toStream(std::ostream & out,const DefineFunctionCommand * c)296 static void toStream(std::ostream& out, const DefineFunctionCommand* c)
297 {
298 Expr func = c->getFunction();
299 const std::vector<Expr>& formals = c->getFormals();
300 Expr formula = c->getFormula();
301 out << "DefineFunction( \"" << func << "\", [";
302 if(formals.size() > 0) {
303 copy( formals.begin(), formals.end() - 1,
304 ostream_iterator<Expr>(out, ", ") );
305 out << formals.back();
306 }
307 out << "], << " << formula << " >> )";
308 }
309
toStream(std::ostream & out,const DeclareTypeCommand * c)310 static void toStream(std::ostream& out, const DeclareTypeCommand* c)
311 {
312 out << "DeclareType(" << c->getSymbol() << "," << c->getArity() << ","
313 << c->getType() << ")";
314 }
315
toStream(std::ostream & out,const DefineTypeCommand * c)316 static void toStream(std::ostream& out, const DefineTypeCommand* c)
317 {
318 const vector<Type>& params = c->getParameters();
319 out << "DefineType(" << c->getSymbol() << ",[";
320 if(params.size() > 0) {
321 copy( params.begin(), params.end() - 1,
322 ostream_iterator<Type>(out, ", ") );
323 out << params.back();
324 }
325 out << "]," << c->getType() << ")";
326 }
327
toStream(std::ostream & out,const DefineNamedFunctionCommand * c)328 static void toStream(std::ostream& out, const DefineNamedFunctionCommand* c)
329 {
330 out << "DefineNamedFunction( ";
331 toStream(out, static_cast<const DefineFunctionCommand*>(c));
332 out << " )";
333 }
334
toStream(std::ostream & out,const SimplifyCommand * c)335 static void toStream(std::ostream& out, const SimplifyCommand* c)
336 {
337 out << "Simplify( << " << c->getTerm() << " >> )";
338 }
339
toStream(std::ostream & out,const GetValueCommand * c)340 static void toStream(std::ostream& out, const GetValueCommand* c)
341 {
342 out << "GetValue( << ";
343 const vector<Expr>& terms = c->getTerms();
344 copy(terms.begin(), terms.end(), ostream_iterator<Expr>(out, ", "));
345 out << ">> )";
346 }
347
toStream(std::ostream & out,const GetModelCommand * c)348 static void toStream(std::ostream& out, const GetModelCommand* c)
349 {
350 out << "GetModel()";
351 }
352
toStream(std::ostream & out,const GetAssignmentCommand * c)353 static void toStream(std::ostream& out, const GetAssignmentCommand* c)
354 {
355 out << "GetAssignment()";
356 }
toStream(std::ostream & out,const GetAssertionsCommand * c)357 static void toStream(std::ostream& out, const GetAssertionsCommand* c)
358 {
359 out << "GetAssertions()";
360 }
toStream(std::ostream & out,const GetProofCommand * c)361 static void toStream(std::ostream& out, const GetProofCommand* c)
362 {
363 out << "GetProof()";
364 }
toStream(std::ostream & out,const SetBenchmarkStatusCommand * c)365 static void toStream(std::ostream& out, const SetBenchmarkStatusCommand* c)
366 {
367 out << "SetBenchmarkStatus(" << c->getStatus() << ")";
368 }
toStream(std::ostream & out,const SetBenchmarkLogicCommand * c)369 static void toStream(std::ostream& out, const SetBenchmarkLogicCommand* c)
370 {
371 out << "SetBenchmarkLogic(" << c->getLogic() << ")";
372 }
toStream(std::ostream & out,const SetInfoCommand * c)373 static void toStream(std::ostream& out, const SetInfoCommand* c)
374 {
375 out << "SetInfo(" << c->getFlag() << ", " << c->getSExpr() << ")";
376 }
377
toStream(std::ostream & out,const GetInfoCommand * c)378 static void toStream(std::ostream& out, const GetInfoCommand* c)
379 {
380 out << "GetInfo(" << c->getFlag() << ")";
381 }
toStream(std::ostream & out,const SetOptionCommand * c)382 static void toStream(std::ostream& out, const SetOptionCommand* c)
383 {
384 out << "SetOption(" << c->getFlag() << ", " << c->getSExpr() << ")";
385 }
386
toStream(std::ostream & out,const GetOptionCommand * c)387 static void toStream(std::ostream& out, const GetOptionCommand* c)
388 {
389 out << "GetOption(" << c->getFlag() << ")";
390 }
391
toStream(std::ostream & out,const DatatypeDeclarationCommand * c)392 static void toStream(std::ostream& out, const DatatypeDeclarationCommand* c)
393 {
394 const vector<DatatypeType>& datatypes = c->getDatatypes();
395 out << "DatatypeDeclarationCommand([";
396 for(vector<DatatypeType>::const_iterator i = datatypes.begin(),
397 i_end = datatypes.end();
398 i != i_end;
399 ++i) {
400 out << *i << ";" << endl;
401 }
402 out << "])";
403 }
404
toStream(std::ostream & out,const CommentCommand * c)405 static void toStream(std::ostream& out, const CommentCommand* c)
406 {
407 out << "CommentCommand([" << c->getComment() << "])";
408 }
409
410 template <class T>
tryToStream(std::ostream & out,const Command * c)411 static bool tryToStream(std::ostream& out, const Command* c)
412 {
413 if(typeid(*c) == typeid(T)) {
414 toStream(out, dynamic_cast<const T*>(c));
415 return true;
416 }
417 return false;
418 }
419
toStream(std::ostream & out,const CommandSuccess * s)420 static void toStream(std::ostream& out, const CommandSuccess* s)
421 {
422 if(Command::printsuccess::getPrintSuccess(out)) {
423 out << "OK" << endl;
424 }
425 }
426
toStream(std::ostream & out,const CommandInterrupted * s)427 static void toStream(std::ostream& out, const CommandInterrupted* s)
428 {
429 out << "INTERRUPTED" << endl;
430 }
431
toStream(std::ostream & out,const CommandUnsupported * s)432 static void toStream(std::ostream& out, const CommandUnsupported* s)
433 {
434 out << "UNSUPPORTED" << endl;
435 }
436
toStream(std::ostream & out,const CommandFailure * s)437 static void toStream(std::ostream& out, const CommandFailure* s)
438 {
439 out << s->getMessage() << endl;
440 }
441
442 template <class T>
tryToStream(std::ostream & out,const CommandStatus * s)443 static bool tryToStream(std::ostream& out, const CommandStatus* s)
444 {
445 if(typeid(*s) == typeid(T)) {
446 toStream(out, dynamic_cast<const T*>(s));
447 return true;
448 }
449 return false;
450 }
451
452 }/* CVC4::printer::ast namespace */
453 }/* CVC4::printer namespace */
454 }/* CVC4 namespace */
455