1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Morgan Deters, Abdalrhman Mohamed, Andrew Reynolds |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 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. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* The pretty-printer interface for the AST output language. |
14 |
|
*/ |
15 |
|
#include "printer/ast/ast_printer.h" |
16 |
|
|
17 |
|
#include <iostream> |
18 |
|
#include <string> |
19 |
|
#include <typeinfo> |
20 |
|
#include <vector> |
21 |
|
|
22 |
|
#include "expr/node_manager_attributes.h" // for VarNameAttr |
23 |
|
#include "expr/node_visitor.h" |
24 |
|
#include "options/language.h" // for LANG_AST |
25 |
|
#include "printer/let_binding.h" |
26 |
|
#include "smt/command.h" |
27 |
|
#include "smt/node_command.h" |
28 |
|
|
29 |
|
using namespace std; |
30 |
|
|
31 |
|
namespace cvc5 { |
32 |
|
namespace printer { |
33 |
|
namespace ast { |
34 |
|
|
35 |
27 |
void AstPrinter::toStream(std::ostream& out, |
36 |
|
TNode n, |
37 |
|
int toDepth, |
38 |
|
size_t dag) const |
39 |
|
{ |
40 |
27 |
if(dag != 0) { |
41 |
4 |
LetBinding lbind(dag + 1); |
42 |
2 |
toStreamWithLetify(out, n, toDepth, &lbind); |
43 |
|
} else { |
44 |
25 |
toStream(out, n, toDepth); |
45 |
|
} |
46 |
27 |
} |
47 |
|
|
48 |
215 |
void AstPrinter::toStream(std::ostream& out, |
49 |
|
TNode n, |
50 |
|
int toDepth, |
51 |
|
LetBinding* lbind) const |
52 |
|
{ |
53 |
|
// null |
54 |
215 |
if(n.getKind() == kind::NULL_EXPR) { |
55 |
|
out << "null"; |
56 |
|
return; |
57 |
|
} |
58 |
|
|
59 |
|
// variable |
60 |
215 |
if(n.getMetaKind() == kind::metakind::VARIABLE) { |
61 |
252 |
string s; |
62 |
126 |
if(n.getAttribute(expr::VarNameAttr(), s)) { |
63 |
126 |
out << s; |
64 |
|
} else { |
65 |
|
out << "var_" << n.getId(); |
66 |
|
} |
67 |
126 |
return; |
68 |
|
} |
69 |
|
|
70 |
89 |
out << '(' << n.getKind(); |
71 |
89 |
if(n.getMetaKind() == kind::metakind::CONSTANT) { |
72 |
|
// constant |
73 |
2 |
out << ' '; |
74 |
2 |
kind::metakind::NodeValueConstPrinter::toStream(out, n); |
75 |
|
} |
76 |
87 |
else if (n.isClosure()) |
77 |
|
{ |
78 |
|
for (size_t i = 0, nchild = n.getNumChildren(); i < nchild; i++) |
79 |
|
{ |
80 |
|
// body is re-letified |
81 |
|
if (i == 1) |
82 |
|
{ |
83 |
|
toStreamWithLetify(out, n[i], toDepth, lbind); |
84 |
|
continue; |
85 |
|
} |
86 |
|
toStream(out, n[i], toDepth < 0 ? toDepth : toDepth - 1, lbind); |
87 |
|
} |
88 |
|
} |
89 |
|
else |
90 |
|
{ |
91 |
|
// operator |
92 |
87 |
if(n.getMetaKind() == kind::metakind::PARAMETERIZED) { |
93 |
|
out << ' '; |
94 |
|
if(toDepth != 0) { |
95 |
|
toStream( |
96 |
|
out, n.getOperator(), toDepth < 0 ? toDepth : toDepth - 1, lbind); |
97 |
|
} else { |
98 |
|
out << "(...)"; |
99 |
|
} |
100 |
|
} |
101 |
299 |
for(TNode::iterator i = n.begin(), |
102 |
87 |
iend = n.end(); |
103 |
299 |
i != iend; |
104 |
|
++i) { |
105 |
212 |
if(i != iend) { |
106 |
212 |
out << ' '; |
107 |
|
} |
108 |
212 |
if(toDepth != 0) { |
109 |
188 |
toStream(out, *i, toDepth < 0 ? toDepth : toDepth - 1, lbind); |
110 |
|
} else { |
111 |
24 |
out << "(...)"; |
112 |
|
} |
113 |
|
} |
114 |
|
} |
115 |
89 |
out << ')'; |
116 |
|
}/* AstPrinter::toStream(TNode) */ |
117 |
|
|
118 |
|
template <class T> |
119 |
|
static bool tryToStream(std::ostream& out, const Command* c); |
120 |
|
|
121 |
|
template <class T> |
122 |
|
static bool tryToStream(std::ostream& out, const CommandStatus* s); |
123 |
|
|
124 |
1 |
void AstPrinter::toStream(std::ostream& out, const CommandStatus* s) const |
125 |
|
{ |
126 |
2 |
if(tryToStream<CommandSuccess>(out, s) || |
127 |
|
tryToStream<CommandFailure>(out, s) || |
128 |
1 |
tryToStream<CommandUnsupported>(out, s) || |
129 |
|
tryToStream<CommandInterrupted>(out, s)) { |
130 |
1 |
return; |
131 |
|
} |
132 |
|
|
133 |
|
out << "ERROR: don't know how to print a CommandStatus of class: " |
134 |
|
<< typeid(*s).name() << endl; |
135 |
|
|
136 |
|
}/* AstPrinter::toStream(CommandStatus*) */ |
137 |
|
|
138 |
|
void AstPrinter::toStream(std::ostream& out, const smt::Model& m) const |
139 |
|
{ |
140 |
|
out << "Model()"; |
141 |
|
} |
142 |
|
|
143 |
|
void AstPrinter::toStreamModelSort(std::ostream& out, |
144 |
|
TypeNode tn, |
145 |
|
const std::vector<Node>& elements) const |
146 |
|
{ |
147 |
|
// shouldn't be called; only the non-Command* version above should be |
148 |
|
Unreachable(); |
149 |
|
} |
150 |
|
|
151 |
|
void AstPrinter::toStreamModelTerm(std::ostream& out, |
152 |
|
const Node& n, |
153 |
|
const Node& value) const |
154 |
|
{ |
155 |
|
// shouldn't be called; only the non-Command* version above should be |
156 |
|
Unreachable(); |
157 |
|
} |
158 |
|
|
159 |
|
void AstPrinter::toStreamCmdEmpty(std::ostream& out, |
160 |
|
const std::string& name) const |
161 |
|
{ |
162 |
|
out << "EmptyCommand(" << name << ')' << std::endl; |
163 |
|
} |
164 |
|
|
165 |
|
void AstPrinter::toStreamCmdEcho(std::ostream& out, |
166 |
|
const std::string& output) const |
167 |
|
{ |
168 |
|
out << "EchoCommand(" << output << ')' << std::endl; |
169 |
|
} |
170 |
|
|
171 |
|
void AstPrinter::toStreamCmdAssert(std::ostream& out, Node n) const |
172 |
|
{ |
173 |
|
out << "Assert(" << n << ')' << std::endl; |
174 |
|
} |
175 |
|
|
176 |
|
void AstPrinter::toStreamCmdPush(std::ostream& out) const |
177 |
|
{ |
178 |
|
out << "Push()" << std::endl; |
179 |
|
} |
180 |
|
|
181 |
|
void AstPrinter::toStreamCmdPop(std::ostream& out) const { |
182 |
|
out << "Pop()" << std::endl; |
183 |
|
} |
184 |
|
|
185 |
|
void AstPrinter::toStreamCmdCheckSat(std::ostream& out, Node n) const |
186 |
|
{ |
187 |
|
if (n.isNull()) |
188 |
|
{ |
189 |
|
out << "CheckSat()"; |
190 |
|
} |
191 |
|
else |
192 |
|
{ |
193 |
|
out << "CheckSat(" << n << ')'; |
194 |
|
} |
195 |
|
out << std::endl; |
196 |
|
} |
197 |
|
|
198 |
|
void AstPrinter::toStreamCmdCheckSatAssuming( |
199 |
|
std::ostream& out, const std::vector<Node>& nodes) const |
200 |
|
{ |
201 |
|
out << "CheckSatAssuming( << "; |
202 |
|
copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, ", ")); |
203 |
|
out << ">> )" << std::endl; |
204 |
|
} |
205 |
|
|
206 |
|
void AstPrinter::toStreamCmdQuery(std::ostream& out, Node n) const |
207 |
|
{ |
208 |
|
out << "Query(" << n << ')' << std::endl; |
209 |
|
} |
210 |
|
|
211 |
|
void AstPrinter::toStreamCmdReset(std::ostream& out) const |
212 |
|
{ |
213 |
|
out << "Reset()" << std::endl; |
214 |
|
} |
215 |
|
|
216 |
|
void AstPrinter::toStreamCmdResetAssertions(std::ostream& out) const |
217 |
|
{ |
218 |
|
out << "ResetAssertions()" << std::endl; |
219 |
|
} |
220 |
|
|
221 |
|
void AstPrinter::toStreamCmdQuit(std::ostream& out) const |
222 |
|
{ |
223 |
|
out << "Quit()" << std::endl; |
224 |
|
} |
225 |
|
|
226 |
|
void AstPrinter::toStreamCmdDeclarationSequence( |
227 |
|
std::ostream& out, const std::vector<Command*>& sequence) const |
228 |
|
{ |
229 |
|
out << "DeclarationSequence[" << endl; |
230 |
|
for (CommandSequence::const_iterator i = sequence.cbegin(); |
231 |
|
i != sequence.cend(); |
232 |
|
++i) |
233 |
|
{ |
234 |
|
out << *i << endl; |
235 |
|
} |
236 |
|
out << "]" << std::endl; |
237 |
|
} |
238 |
|
|
239 |
|
void AstPrinter::toStreamCmdCommandSequence( |
240 |
|
std::ostream& out, const std::vector<Command*>& sequence) const |
241 |
|
{ |
242 |
|
out << "CommandSequence[" << endl; |
243 |
|
for (CommandSequence::const_iterator i = sequence.cbegin(); |
244 |
|
i != sequence.cend(); |
245 |
|
++i) |
246 |
|
{ |
247 |
|
out << *i << endl; |
248 |
|
} |
249 |
|
out << "]" << std::endl; |
250 |
|
} |
251 |
|
|
252 |
|
void AstPrinter::toStreamCmdDeclareFunction(std::ostream& out, |
253 |
|
const std::string& id, |
254 |
|
TypeNode type) const |
255 |
|
{ |
256 |
|
out << "Declare(" << id << "," << type << ')' << std::endl; |
257 |
|
} |
258 |
|
|
259 |
|
void AstPrinter::toStreamCmdDefineFunction(std::ostream& out, |
260 |
|
const std::string& id, |
261 |
|
const std::vector<Node>& formals, |
262 |
|
TypeNode range, |
263 |
|
Node formula) const |
264 |
|
{ |
265 |
|
out << "DefineFunction( \"" << id << "\", ["; |
266 |
|
if (formals.size() > 0) |
267 |
|
{ |
268 |
|
copy(formals.begin(), formals.end() - 1, ostream_iterator<Node>(out, ", ")); |
269 |
|
out << formals.back(); |
270 |
|
} |
271 |
|
out << "], << " << formula << " >> )" << std::endl; |
272 |
|
} |
273 |
|
|
274 |
|
void AstPrinter::toStreamCmdDeclareType(std::ostream& out, |
275 |
|
TypeNode type) const |
276 |
|
{ |
277 |
|
out << "DeclareType(" << type << ')' << std::endl; |
278 |
|
} |
279 |
|
|
280 |
|
void AstPrinter::toStreamCmdDefineType(std::ostream& out, |
281 |
|
const std::string& id, |
282 |
|
const std::vector<TypeNode>& params, |
283 |
|
TypeNode t) const |
284 |
|
{ |
285 |
|
out << "DefineType(" << id << ",["; |
286 |
|
if (params.size() > 0) |
287 |
|
{ |
288 |
|
copy(params.begin(), |
289 |
|
params.end() - 1, |
290 |
|
ostream_iterator<TypeNode>(out, ", ")); |
291 |
|
out << params.back(); |
292 |
|
} |
293 |
|
out << "]," << t << ')' << std::endl; |
294 |
|
} |
295 |
|
|
296 |
|
void AstPrinter::toStreamCmdSimplify(std::ostream& out, Node n) const |
297 |
|
{ |
298 |
|
out << "Simplify( << " << n << " >> )" << std::endl; |
299 |
|
} |
300 |
|
|
301 |
|
void AstPrinter::toStreamCmdGetValue(std::ostream& out, |
302 |
|
const std::vector<Node>& nodes) const |
303 |
|
{ |
304 |
|
out << "GetValue( << "; |
305 |
|
copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, ", ")); |
306 |
|
out << ">> )" << std::endl; |
307 |
|
} |
308 |
|
|
309 |
|
void AstPrinter::toStreamCmdGetModel(std::ostream& out) const |
310 |
|
{ |
311 |
|
out << "GetModel()" << std::endl; |
312 |
|
} |
313 |
|
|
314 |
|
void AstPrinter::toStreamCmdGetAssignment(std::ostream& out) const |
315 |
|
{ |
316 |
|
out << "GetAssignment()" << std::endl; |
317 |
|
} |
318 |
|
|
319 |
|
void AstPrinter::toStreamCmdGetAssertions(std::ostream& out) const |
320 |
|
{ |
321 |
|
out << "GetAssertions()" << std::endl; |
322 |
|
} |
323 |
|
|
324 |
|
void AstPrinter::toStreamCmdGetProof(std::ostream& out) const |
325 |
|
{ |
326 |
|
out << "GetProof()" << std::endl; |
327 |
|
} |
328 |
|
|
329 |
|
void AstPrinter::toStreamCmdGetUnsatCore(std::ostream& out) const |
330 |
|
{ |
331 |
|
out << "GetUnsatCore()" << std::endl; |
332 |
|
} |
333 |
|
|
334 |
|
void AstPrinter::toStreamCmdSetBenchmarkStatus(std::ostream& out, |
335 |
|
Result::Sat status) const |
336 |
|
{ |
337 |
|
out << "SetBenchmarkStatus(" << status << ')' << std::endl; |
338 |
|
} |
339 |
|
|
340 |
|
void AstPrinter::toStreamCmdSetBenchmarkLogic(std::ostream& out, |
341 |
|
const std::string& logic) const |
342 |
|
{ |
343 |
|
out << "SetBenchmarkLogic(" << logic << ')' << std::endl; |
344 |
|
} |
345 |
|
|
346 |
|
void AstPrinter::toStreamCmdSetInfo(std::ostream& out, |
347 |
|
const std::string& flag, |
348 |
|
const std::string& value) const |
349 |
|
{ |
350 |
|
out << "SetInfo(" << flag << ", " << value << ')' << std::endl; |
351 |
|
} |
352 |
|
|
353 |
|
void AstPrinter::toStreamCmdGetInfo(std::ostream& out, |
354 |
|
const std::string& flag) const |
355 |
|
{ |
356 |
|
out << "GetInfo(" << flag << ')' << std::endl; |
357 |
|
} |
358 |
|
|
359 |
|
void AstPrinter::toStreamCmdSetOption(std::ostream& out, |
360 |
|
const std::string& flag, |
361 |
|
const std::string& value) const |
362 |
|
{ |
363 |
|
out << "SetOption(" << flag << ", " << value << ')' << std::endl; |
364 |
|
} |
365 |
|
|
366 |
|
void AstPrinter::toStreamCmdGetOption(std::ostream& out, |
367 |
|
const std::string& flag) const |
368 |
|
{ |
369 |
|
out << "GetOption(" << flag << ')' << std::endl; |
370 |
|
} |
371 |
|
|
372 |
|
void AstPrinter::toStreamCmdDatatypeDeclaration( |
373 |
|
std::ostream& out, const std::vector<TypeNode>& datatypes) const |
374 |
|
{ |
375 |
|
out << "DatatypeDeclarationCommand(["; |
376 |
|
for (const TypeNode& t : datatypes) |
377 |
|
{ |
378 |
|
out << t << ";" << endl; |
379 |
|
} |
380 |
|
out << "])" << std::endl; |
381 |
|
} |
382 |
|
|
383 |
|
void AstPrinter::toStreamCmdComment(std::ostream& out, |
384 |
|
const std::string& comment) const |
385 |
|
{ |
386 |
|
out << "CommentCommand([" << comment << "])" << std::endl; |
387 |
|
} |
388 |
|
|
389 |
2 |
void AstPrinter::toStreamWithLetify(std::ostream& out, |
390 |
|
Node n, |
391 |
|
int toDepth, |
392 |
|
LetBinding* lbind) const |
393 |
|
{ |
394 |
2 |
if (lbind == nullptr) |
395 |
|
{ |
396 |
|
toStream(out, n, toDepth); |
397 |
|
return; |
398 |
|
} |
399 |
4 |
std::stringstream cparen; |
400 |
4 |
std::vector<Node> letList; |
401 |
2 |
lbind->letify(n, letList); |
402 |
2 |
if (!letList.empty()) |
403 |
|
{ |
404 |
|
std::map<Node, uint32_t>::const_iterator it; |
405 |
|
out << "(LET "; |
406 |
|
cparen << ")"; |
407 |
|
bool first = true; |
408 |
|
for (size_t i = 0, nlets = letList.size(); i < nlets; i++) |
409 |
|
{ |
410 |
|
if (!first) |
411 |
|
{ |
412 |
|
out << ", "; |
413 |
|
} |
414 |
|
else |
415 |
|
{ |
416 |
|
first = false; |
417 |
|
} |
418 |
|
Node nl = letList[i]; |
419 |
|
uint32_t id = lbind->getId(nl); |
420 |
|
out << "_let_" << id << " := "; |
421 |
|
Node nlc = lbind->convert(nl, "_let_", false); |
422 |
|
toStream(out, nlc, toDepth, lbind); |
423 |
|
} |
424 |
|
out << " IN "; |
425 |
|
} |
426 |
4 |
Node nc = lbind->convert(n, "_let_"); |
427 |
|
// print the body, passing the lbind object |
428 |
2 |
toStream(out, nc, toDepth, lbind); |
429 |
2 |
out << cparen.str(); |
430 |
2 |
lbind->popScope(); |
431 |
|
} |
432 |
|
|
433 |
|
template <class T> |
434 |
|
static bool tryToStream(std::ostream& out, const Command* c) |
435 |
|
{ |
436 |
|
if(typeid(*c) == typeid(T)) { |
437 |
|
toStream(out, dynamic_cast<const T*>(c)); |
438 |
|
return true; |
439 |
|
} |
440 |
|
return false; |
441 |
|
} |
442 |
|
|
443 |
1 |
static void toStream(std::ostream& out, const CommandSuccess* s) |
444 |
|
{ |
445 |
1 |
if(Command::printsuccess::getPrintSuccess(out)) { |
446 |
|
out << "OK" << endl; |
447 |
|
} |
448 |
1 |
} |
449 |
|
|
450 |
|
static void toStream(std::ostream& out, const CommandInterrupted* s) |
451 |
|
{ |
452 |
|
out << "INTERRUPTED" << endl; |
453 |
|
} |
454 |
|
|
455 |
|
static void toStream(std::ostream& out, const CommandUnsupported* s) |
456 |
|
{ |
457 |
|
out << "UNSUPPORTED" << endl; |
458 |
|
} |
459 |
|
|
460 |
|
static void toStream(std::ostream& out, const CommandFailure* s) |
461 |
|
{ |
462 |
|
out << s->getMessage() << endl; |
463 |
|
} |
464 |
|
|
465 |
|
template <class T> |
466 |
1 |
static bool tryToStream(std::ostream& out, const CommandStatus* s) |
467 |
|
{ |
468 |
1 |
if(typeid(*s) == typeid(T)) { |
469 |
1 |
toStream(out, dynamic_cast<const T*>(s)); |
470 |
1 |
return true; |
471 |
|
} |
472 |
|
return false; |
473 |
|
} |
474 |
|
|
475 |
|
} // namespace ast |
476 |
|
} // namespace printer |
477 |
29505 |
} // namespace cvc5 |