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