GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/printer/smt2/smt2_printer.cpp Lines: 634 1218 52.1 %
Date: 2021-05-22 Branches: 1032 3262 31.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Abdalrhman Mohamed
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 SMT2 output language.
14
 */
15
16
#include "printer/smt2/smt2_printer.h"
17
18
#include <iostream>
19
#include <list>
20
#include <string>
21
#include <typeinfo>
22
#include <vector>
23
24
#include "api/cpp/cvc5.h"
25
#include "expr/dtype.h"
26
#include "expr/dtype_cons.h"
27
#include "expr/node_manager_attributes.h"
28
#include "expr/node_visitor.h"
29
#include "expr/sequence.h"
30
#include "options/bv_options.h"
31
#include "options/language.h"
32
#include "options/printer_options.h"
33
#include "options/smt_options.h"
34
#include "printer/let_binding.h"
35
#include "proof/unsat_core.h"
36
#include "smt/command.h"
37
#include "smt/node_command.h"
38
#include "smt/smt_engine.h"
39
#include "smt_util/boolean_simplification.h"
40
#include "theory/arrays/theory_arrays_rewriter.h"
41
#include "theory/datatypes/sygus_datatype_utils.h"
42
#include "theory/quantifiers/quantifiers_attributes.h"
43
#include "theory/theory_model.h"
44
#include "util/smt2_quote_string.h"
45
46
using namespace std;
47
48
namespace cvc5 {
49
namespace printer {
50
namespace smt2 {
51
52
196216
static void toStreamRational(std::ostream& out,
53
                             const Rational& r,
54
                             bool decimal,
55
                             Variant v)
56
{
57
196216
  bool neg = r.sgn() < 0;
58
  // Print the rational, possibly as decimal.
59
  // Notice that we print (/ (- 5) 3) instead of (- (/ 5 3)),
60
  // the former is compliant with real values in the smt lib standard.
61
196216
  if (r.isIntegral())
62
  {
63
196095
    if (neg)
64
    {
65
77543
      out << "(- " << -r;
66
    }
67
    else
68
    {
69
118552
      out << r;
70
    }
71
196095
    if (decimal)
72
    {
73
16
      out << ".0";
74
    }
75
196095
    if (neg)
76
    {
77
77543
      out << ")";
78
    }
79
  }
80
  else
81
  {
82
121
    out << "(/ ";
83
121
    if (neg)
84
    {
85
60
      Rational abs_r = (-r);
86
30
      out << "(- " << abs_r.getNumerator();
87
30
      out << ") " << abs_r.getDenominator();
88
    }
89
    else
90
    {
91
91
      out << r.getNumerator();
92
91
      out << ' ' << r.getDenominator();
93
    }
94
121
    out << ')';
95
  }
96
196216
}
97
98
79890
void Smt2Printer::toStream(std::ostream& out,
99
                           TNode n,
100
                           int toDepth,
101
                           size_t dag) const
102
{
103
79890
  if(dag != 0) {
104
105976
    LetBinding lbind(dag + 1);
105
53002
    toStreamWithLetify(out, n, toDepth, &lbind);
106
  } else {
107
26902
    toStream(out, n, toDepth);
108
  }
109
79876
}
110
111
52988
void Smt2Printer::toStreamWithLetify(std::ostream& out,
112
                                     Node n,
113
                                     int toDepth,
114
                                     LetBinding* lbind) const
115
{
116
52988
  if (lbind == nullptr)
117
  {
118
    toStream(out, n, toDepth);
119
    return;
120
  }
121
105976
  std::stringstream cparen;
122
105976
  std::vector<Node> letList;
123
52988
  lbind->letify(n, letList);
124
52988
  if (!letList.empty())
125
  {
126
33123
    std::map<Node, uint32_t>::const_iterator it;
127
125494
    for (size_t i = 0, nlets = letList.size(); i < nlets; i++)
128
    {
129
184742
      Node nl = letList[i];
130
92371
      out << "(let ((";
131
92371
      uint32_t id = lbind->getId(nl);
132
92371
      out << "_let_" << id << " ";
133
184742
      Node nlc = lbind->convert(nl, "_let_", false);
134
92371
      toStream(out, nlc, toDepth, lbind);
135
92371
      out << ")) ";
136
92371
      cparen << ")";
137
    }
138
  }
139
105976
  Node nc = lbind->convert(n, "_let_");
140
  // print the body, passing the lbind object
141
52974
  toStream(out, nc, toDepth, lbind);
142
52974
  out << cparen.str();
143
52974
  lbind->popScope();
144
}
145
146
1622839
void Smt2Printer::toStream(std::ostream& out,
147
                           TNode n,
148
                           int toDepth,
149
                           LetBinding* lbind) const
150
{
151
  // null
152
1622839
  if(n.getKind() == kind::NULL_EXPR) {
153
    out << "null";
154
1003797
    return;
155
  }
156
157
1622839
  NodeManager* nm = NodeManager::currentNM();
158
  // constant
159
1622839
  if(n.getMetaKind() == kind::metakind::CONSTANT) {
160
250113
    switch(n.getKind()) {
161
11176
    case kind::TYPE_CONSTANT:
162
11176
      switch(n.getConst<TypeConstant>()) {
163
2166
      case BOOLEAN_TYPE: out << "Bool"; break;
164
524
      case REAL_TYPE: out << "Real"; break;
165
7885
      case INTEGER_TYPE: out << "Int"; break;
166
535
      case STRING_TYPE: out << "String"; break;
167
4
      case REGEXP_TYPE: out << "RegLan"; break;
168
62
      case ROUNDINGMODE_TYPE: out << "RoundingMode"; break;
169
      default:
170
        // fall back on whatever operator<< does on underlying type; we
171
        // might luck out and be SMT-LIB v2 compliant
172
        kind::metakind::NodeValueConstPrinter::toStream(out, n);
173
      }
174
11176
      break;
175
4088
    case kind::BITVECTOR_TYPE:
176
4088
      out << "(_ BitVec " << n.getConst<BitVectorSize>().d_size << ")";
177
4088
      break;
178
207
    case kind::FLOATINGPOINT_TYPE:
179
207
      out << "(_ FloatingPoint "
180
207
          << n.getConst<FloatingPointSize>().exponentWidth() << " "
181
207
          << n.getConst<FloatingPointSize>().significandWidth() << ")";
182
207
      break;
183
200
    case kind::CONST_BITVECTOR:
184
    {
185
200
      const BitVector& bv = n.getConst<BitVector>();
186
404
      if (options::bvPrintConstsAsIndexedSymbols())
187
      {
188
2
        out << "(_ bv" << bv.getValue() << " " << bv.getSize() << ")";
189
      }
190
      else
191
      {
192
198
        out << "#b" << bv.toString();
193
      }
194
200
      break;
195
    }
196
2
    case kind::CONST_FLOATINGPOINT:
197
    {
198
4
      out << n.getConst<FloatingPoint>().toString(
199
2
          options::bvPrintConstsAsIndexedSymbols());
200
2
      break;
201
    }
202
2
    case kind::CONST_ROUNDINGMODE:
203
2
      switch (n.getConst<RoundingMode>()) {
204
        case ROUND_NEAREST_TIES_TO_EVEN: out << "roundNearestTiesToEven"; break;
205
2
        case ROUND_NEAREST_TIES_TO_AWAY: out << "roundNearestTiesToAway"; break;
206
        case ROUND_TOWARD_POSITIVE: out << "roundTowardPositive"; break;
207
        case ROUND_TOWARD_NEGATIVE: out << "roundTowardNegative"; break;
208
        case ROUND_TOWARD_ZERO: out << "roundTowardZero"; break;
209
        default:
210
          Unreachable() << "Invalid value of rounding mode constant ("
211
                        << n.getConst<RoundingMode>() << ")";
212
      }
213
2
      break;
214
33954
    case kind::CONST_BOOLEAN:
215
      // the default would print "1" or "0" for bool, that's not correct
216
      // for our purposes
217
33954
      out << (n.getConst<bool>() ? "true" : "false");
218
33954
      break;
219
    case kind::BUILTIN:
220
      out << smtKindString(n.getConst<Kind>(), d_variant);
221
      break;
222
196200
    case kind::CONST_RATIONAL: {
223
196200
      const Rational& r = n.getConst<Rational>();
224
196200
      toStreamRational(out, r, false, d_variant);
225
196200
      break;
226
    }
227
228
2199
    case kind::CONST_STRING: {
229
4398
      std::string s = n.getConst<String>().toString();
230
2199
      out << '"';
231
4746
      for(size_t i = 0; i < s.size(); ++i) {
232
2547
        char c = s[i];
233
2547
        if(c == '"') {
234
4
          out << "\"\"";
235
        } else {
236
2543
          out << c;
237
        }
238
      }
239
2199
      out << '"';
240
2199
      break;
241
    }
242
5
    case kind::CONST_SEQUENCE:
243
    {
244
5
      const Sequence& sn = n.getConst<Sequence>();
245
5
      const std::vector<Node>& snvec = sn.getVec();
246
5
      if (snvec.empty())
247
      {
248
5
        out << "(as seq.empty ";
249
5
        toStreamType(out, n.getType());
250
5
        out << ")";
251
      }
252
5
      if (snvec.size() > 1)
253
      {
254
        out << "(seq.++ ";
255
      }
256
5
      for (const Node& snvc : snvec)
257
      {
258
        out << "(seq.unit " << snvc << ")";
259
      }
260
5
      if (snvec.size() > 1)
261
      {
262
        out << ")";
263
      }
264
5
      break;
265
    }
266
267
17
    case kind::STORE_ALL: {
268
34
      ArrayStoreAll asa = n.getConst<ArrayStoreAll>();
269
17
      out << "((as const ";
270
17
      toStreamType(out, asa.getType());
271
17
      out << ") " << asa.getValue() << ")";
272
17
      break;
273
    }
274
275
1994
    case kind::DATATYPE_TYPE:
276
    {
277
      const DType& dt = (NodeManager::currentNM()->getDTypeForIndex(
278
1994
          n.getConst<DatatypeIndexConstant>().getIndex()));
279
1994
      if (dt.isTuple())
280
      {
281
6
        unsigned int nargs = dt[0].getNumArgs();
282
6
        if (nargs == 0)
283
        {
284
          out << "Tuple";
285
        }
286
        else
287
        {
288
6
          out << "(Tuple";
289
20
          for (unsigned int i = 0; i < nargs; i++)
290
          {
291
14
            out << " ";
292
14
            toStreamType(out, dt[0][i].getRangeType());
293
          }
294
6
          out << ")";
295
        }
296
      }
297
      else
298
      {
299
1988
        out << cvc5::quoteSymbol(dt.getName());
300
      }
301
1994
      break;
302
    }
303
304
1
    case kind::UNINTERPRETED_CONSTANT: {
305
1
      const UninterpretedConstant& uc = n.getConst<UninterpretedConstant>();
306
2
      std::stringstream ss;
307
1
      ss << "(as @" << uc << " " << n.getType() << ")";
308
1
      out << ss.str();
309
1
      break;
310
    }
311
312
6
    case kind::EMPTYSET:
313
6
      out << "(as emptyset ";
314
6
      toStreamType(out, n.getConst<EmptySet>().getType());
315
6
      out << ")";
316
6
      break;
317
318
    case kind::EMPTYBAG:
319
      out << "(as emptybag ";
320
      toStreamType(out, n.getConst<EmptyBag>().getType());
321
      out << ")";
322
      break;
323
8
    case kind::BITVECTOR_EXTRACT_OP:
324
    {
325
8
      BitVectorExtract p = n.getConst<BitVectorExtract>();
326
8
      out << "(_ extract " << p.d_high << ' ' << p.d_low << ")";
327
8
      break;
328
    }
329
4
    case kind::BITVECTOR_REPEAT_OP:
330
4
      out << "(_ repeat " << n.getConst<BitVectorRepeat>().d_repeatAmount
331
4
          << ")";
332
4
      break;
333
16
    case kind::BITVECTOR_ZERO_EXTEND_OP:
334
16
      out << "(_ zero_extend "
335
16
          << n.getConst<BitVectorZeroExtend>().d_zeroExtendAmount << ")";
336
16
      break;
337
    case kind::BITVECTOR_SIGN_EXTEND_OP:
338
      out << "(_ sign_extend "
339
          << n.getConst<BitVectorSignExtend>().d_signExtendAmount << ")";
340
      break;
341
    case kind::BITVECTOR_ROTATE_LEFT_OP:
342
      out << "(_ rotate_left "
343
          << n.getConst<BitVectorRotateLeft>().d_rotateLeftAmount << ")";
344
      break;
345
    case kind::BITVECTOR_ROTATE_RIGHT_OP:
346
      out << "(_ rotate_right "
347
          << n.getConst<BitVectorRotateRight>().d_rotateRightAmount << ")";
348
      break;
349
20
    case kind::INT_TO_BITVECTOR_OP:
350
20
      out << "(_ int2bv " << n.getConst<IntToBitVector>().d_size << ")";
351
20
      break;
352
    case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR_OP:
353
      out << "(_ to_fp "
354
          << n.getConst<FloatingPointToFPIEEEBitVector>()
355
                 .getSize()
356
                 .exponentWidth()
357
          << ' '
358
          << n.getConst<FloatingPointToFPIEEEBitVector>()
359
                 .getSize()
360
                 .significandWidth()
361
          << ")";
362
      break;
363
    case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT_OP:
364
      out << "(_ to_fp "
365
          << n.getConst<FloatingPointToFPFloatingPoint>()
366
                 .getSize()
367
                 .exponentWidth()
368
          << ' '
369
          << n.getConst<FloatingPointToFPFloatingPoint>()
370
                 .getSize()
371
                 .significandWidth()
372
          << ")";
373
      break;
374
    case kind::FLOATINGPOINT_TO_FP_REAL_OP:
375
      out << "(_ to_fp "
376
          << n.getConst<FloatingPointToFPReal>().getSize().exponentWidth()
377
          << ' '
378
          << n.getConst<FloatingPointToFPReal>().getSize().significandWidth()
379
          << ")";
380
      break;
381
    case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR_OP:
382
      out << "(_ to_fp "
383
          << n.getConst<FloatingPointToFPSignedBitVector>()
384
                 .getSize()
385
                 .exponentWidth()
386
          << ' '
387
          << n.getConst<FloatingPointToFPSignedBitVector>()
388
                 .getSize()
389
                 .significandWidth()
390
          << ")";
391
      break;
392
    case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR_OP:
393
      out << "(_ to_fp_unsigned "
394
          << n.getConst<FloatingPointToFPUnsignedBitVector>()
395
                 .getSize()
396
                 .exponentWidth()
397
          << ' '
398
          << n.getConst<FloatingPointToFPUnsignedBitVector>()
399
                 .getSize()
400
                 .significandWidth()
401
          << ")";
402
      break;
403
2
    case kind::FLOATINGPOINT_TO_FP_GENERIC_OP:
404
2
      out << "(_ to_fp "
405
4
          << n.getConst<FloatingPointToFPGeneric>().getSize().exponentWidth()
406
2
          << ' '
407
4
          << n.getConst<FloatingPointToFPGeneric>().getSize().significandWidth()
408
2
          << ")";
409
2
      break;
410
    case kind::FLOATINGPOINT_TO_UBV_OP:
411
      out << "(_ fp.to_ubv "
412
          << n.getConst<FloatingPointToUBV>().d_bv_size.d_size << ")";
413
      break;
414
    case kind::FLOATINGPOINT_TO_SBV_OP:
415
      out << "(_ fp.to_sbv "
416
          << n.getConst<FloatingPointToSBV>().d_bv_size.d_size << ")";
417
      break;
418
    case kind::FLOATINGPOINT_TO_UBV_TOTAL_OP:
419
      out << "(_ fp.to_ubv_total "
420
          << n.getConst<FloatingPointToUBVTotal>().d_bv_size.d_size << ")";
421
      break;
422
    case kind::FLOATINGPOINT_TO_SBV_TOTAL_OP:
423
      out << "(_ fp.to_sbv_total "
424
          << n.getConst<FloatingPointToSBVTotal>().d_bv_size.d_size << ")";
425
      break;
426
2
    case kind::REGEXP_REPEAT_OP:
427
2
      out << "(_ re.^ " << n.getConst<RegExpRepeat>().d_repeatAmount << ")";
428
2
      break;
429
2
    case kind::REGEXP_LOOP_OP:
430
2
      out << "(_ re.loop " << n.getConst<RegExpLoop>().d_loopMinOcc << " "
431
2
          << n.getConst<RegExpLoop>().d_loopMaxOcc << ")";
432
2
      break;
433
8
    default:
434
      // fall back on whatever operator<< does on underlying type; we
435
      // might luck out and be SMT-LIB v2 compliant
436
8
      kind::metakind::NodeValueConstPrinter::toStream(out, n);
437
    }
438
439
250113
    return;
440
  }
441
442
1372726
  if(n.getKind() == kind::SORT_TYPE) {
443
12388
    string name;
444
6194
    if(n.getNumChildren() != 0) {
445
28
      out << '(';
446
    }
447
6194
    if(n.getAttribute(expr::VarNameAttr(), name)) {
448
6194
      out << cvc5::quoteSymbol(name);
449
    }
450
6194
    if(n.getNumChildren() != 0) {
451
60
      for(unsigned i = 0; i < n.getNumChildren(); ++i) {
452
32
	      out << ' ';
453
32
              toStream(out, n[i], toDepth);
454
      }
455
28
      out << ')';
456
    }
457
6194
    return;
458
  }
459
460
  // determine if we are printing out a type ascription, store the argument of
461
  // the type ascription into type_asc_arg.
462
1366532
  Kind k = n.getKind();
463
1985574
  Node type_asc_arg;
464
1985574
  TypeNode force_nt;
465
1366532
  if (k == kind::APPLY_TYPE_ASCRIPTION)
466
  {
467
20
    force_nt = n.getOperator().getConst<AscriptionType>().getType();
468
20
    type_asc_arg = n[0];
469
  }
470
1366512
  else if (k == kind::CAST_TO_REAL)
471
  {
472
16
    force_nt = nm->realType();
473
16
    type_asc_arg = n[0];
474
  }
475
1366532
  if (!type_asc_arg.isNull())
476
  {
477
36
    if (force_nt.isReal())
478
    {
479
      // we prefer using (/ x 1) instead of (to_real x) here.
480
      // the reason is that (/ x 1) is SMT-LIB compliant when x is a constant
481
      // or the logic is non-linear, whereas (to_real x) is compliant when
482
      // the logic is mixed int/real. The former occurs more frequently.
483
16
      bool is_int = force_nt.isInteger();
484
      // If constant rational, print as special case
485
16
      if (type_asc_arg.getKind() == kind::CONST_RATIONAL)
486
      {
487
16
        const Rational& r = type_asc_arg.getConst<Rational>();
488
16
        toStreamRational(out, r, !is_int, d_variant);
489
      }
490
      else
491
      {
492
        out << "("
493
            << smtKindString(is_int ? kind::TO_INTEGER : kind::DIVISION,
494
                             d_variant)
495
            << " ";
496
        toStream(out, type_asc_arg, toDepth, lbind);
497
        if (!is_int)
498
        {
499
          out << " 1";
500
        }
501
        out << ")";
502
      }
503
    }
504
    else
505
    {
506
      // use type ascription
507
20
      out << "(as ";
508
20
      toStream(out, type_asc_arg, toDepth < 0 ? toDepth : toDepth - 1, lbind);
509
20
      out << " " << force_nt << ")";
510
    }
511
36
    return;
512
  }
513
514
  // variable
515
1366496
  if (n.isVar())
516
  {
517
1491258
    string s;
518
745629
    if (n.getAttribute(expr::VarNameAttr(), s))
519
    {
520
743664
      out << cvc5::quoteSymbol(s);
521
    }
522
    else
523
    {
524
1965
      if (n.getKind() == kind::VARIABLE)
525
      {
526
        out << "var_";
527
      }
528
      else
529
      {
530
1965
        out << n.getKind() << '_';
531
      }
532
1965
      out << n.getId();
533
    }
534
745629
    return;
535
  }
536
537
620867
  bool stillNeedToPrintParams = true;
538
620867
  bool forceBinary = false; // force N-ary to binary when outputing children
539
  // operator
540
620867
  if (n.getNumChildren() != 0 && k != kind::CONSTRUCTOR_TYPE)
541
  {
542
619924
    out << '(';
543
  }
544
620867
  switch(k) {
545
    // builtin theory
546
40735
  case kind::EQUAL:
547
  case kind::DISTINCT:
548
40735
    out << smtKindString(k, d_variant) << " ";
549
40735
    break;
550
890
  case kind::FUNCTION_TYPE:
551
890
    out << "->";
552
3635
    for (Node nc : n)
553
    {
554
2745
      out << " ";
555
2745
      toStream(out, nc, toDepth);
556
890
    }
557
890
    out << ")";
558
890
    return;
559
367353
  case kind::SEXPR: break;
560
561
    // bool theory
562
23689
  case kind::NOT:
563
  case kind::AND:
564
  case kind::IMPLIES:
565
  case kind::OR:
566
  case kind::XOR:
567
  case kind::ITE:
568
23689
    out << smtKindString(k, d_variant) << " ";
569
23689
    break;
570
571
  // uf theory
572
43056
  case kind::APPLY_UF: break;
573
  // higher-order
574
  case kind::HO_APPLY:
575
    if (!options::flattenHOChains())
576
    {
577
      break;
578
    }
579
    // collapse "@" chains, i.e.
580
    //
581
    // ((a b) c) --> (a b c)
582
    //
583
    // (((a b) ((c d) e)) f) --> (a b (c d e) f)
584
    {
585
      Node head = n;
586
      std::vector<Node> args;
587
      while (head.getKind() == kind::HO_APPLY)
588
      {
589
        args.insert(args.begin(), head[1]);
590
        head = head[0];
591
      }
592
      toStream(out, head, toDepth, lbind);
593
      for (unsigned i = 0, size = args.size(); i < size; ++i)
594
      {
595
        out << " ";
596
        toStream(out, args[i], toDepth, lbind);
597
      }
598
      out << ")";
599
    }
600
    return;
601
602
  case kind::MATCH:
603
    out << smtKindString(k, d_variant) << " ";
604
    toStream(out, n[0], toDepth, lbind);
605
    out << " (";
606
    for (size_t i = 1, nchild = n.getNumChildren(); i < nchild; i++)
607
    {
608
      if (i > 1)
609
      {
610
        out << " ";
611
      }
612
      toStream(out, n[i], toDepth, lbind);
613
    }
614
    out << "))";
615
    return;
616
  case kind::MATCH_BIND_CASE:
617
    // ignore the binder
618
    toStream(out, n[1], toDepth, lbind);
619
    out << " ";
620
    toStream(out, n[2], toDepth, lbind);
621
    out << ")";
622
    return;
623
  case kind::MATCH_CASE:
624
    // do nothing
625
    break;
626
627
  // arith theory
628
129100
  case kind::PLUS:
629
  case kind::MULT:
630
  case kind::NONLINEAR_MULT:
631
  case kind::EXPONENTIAL:
632
  case kind::SINE:
633
  case kind::COSINE:
634
  case kind::TANGENT:
635
  case kind::COSECANT:
636
  case kind::SECANT:
637
  case kind::COTANGENT:
638
  case kind::ARCSINE:
639
  case kind::ARCCOSINE:
640
  case kind::ARCTANGENT:
641
  case kind::ARCCOSECANT:
642
  case kind::ARCSECANT:
643
  case kind::ARCCOTANGENT:
644
  case kind::PI:
645
  case kind::SQRT:
646
  case kind::MINUS:
647
  case kind::UMINUS:
648
  case kind::LT:
649
  case kind::LEQ:
650
  case kind::GT:
651
  case kind::GEQ:
652
  case kind::DIVISION:
653
  case kind::DIVISION_TOTAL:
654
  case kind::INTS_DIVISION:
655
  case kind::INTS_DIVISION_TOTAL:
656
  case kind::INTS_MODULUS:
657
  case kind::INTS_MODULUS_TOTAL:
658
  case kind::ABS:
659
  case kind::IS_INTEGER:
660
  case kind::TO_INTEGER:
661
  case kind::TO_REAL:
662
  case kind::POW:
663
129100
    out << smtKindString(k, d_variant) << " ";
664
129100
    break;
665
1
  case kind::IAND:
666
1
    out << "(_ iand " << n.getOperator().getConst<IntAnd>().d_size << ") ";
667
1
    stillNeedToPrintParams = false;
668
1
    break;
669
670
  case kind::DIVISIBLE:
671
    out << "(_ divisible " << n.getOperator().getConst<Divisible>().k << ")";
672
    stillNeedToPrintParams = false;
673
    break;
674
  case kind::INDEXED_ROOT_PREDICATE_OP:
675
  {
676
    const IndexedRootPredicate& irp = n.getConst<IndexedRootPredicate>();
677
    out << "(_ root_predicate " << irp.d_index << ")";
678
    break;
679
  }
680
681
    // arrays theory
682
470
  case kind::SELECT:
683
  case kind::STORE:
684
  case kind::PARTIAL_SELECT_0:
685
  case kind::PARTIAL_SELECT_1:
686
  case kind::ARRAY_TYPE:
687
470
  case kind::EQ_RANGE: out << smtKindString(k, d_variant) << " "; break;
688
689
  // string theory
690
433
  case kind::STRING_CONCAT:
691
433
    out << "str.++ ";
692
433
    break;
693
6
  case kind::STRING_IN_REGEXP: {
694
12
    stringstream ss;
695
6
    out << smtKindString(k, d_variant) << " ";
696
6
    break;
697
  }
698
5051
  case kind::STRING_LENGTH:
699
  case kind::STRING_SUBSTR:
700
  case kind::STRING_UPDATE:
701
  case kind::STRING_CHARAT:
702
  case kind::STRING_STRCTN:
703
  case kind::STRING_STRIDOF:
704
  case kind::STRING_STRREPL:
705
  case kind::STRING_STRREPLALL:
706
  case kind::STRING_REPLACE_RE:
707
  case kind::STRING_REPLACE_RE_ALL:
708
  case kind::STRING_TOLOWER:
709
  case kind::STRING_TOUPPER:
710
  case kind::STRING_REV:
711
  case kind::STRING_PREFIX:
712
  case kind::STRING_SUFFIX:
713
  case kind::STRING_LEQ:
714
  case kind::STRING_LT:
715
  case kind::STRING_ITOS:
716
  case kind::STRING_STOI:
717
  case kind::STRING_FROM_CODE:
718
  case kind::STRING_TO_CODE:
719
  case kind::STRING_TO_REGEXP:
720
  case kind::REGEXP_CONCAT:
721
  case kind::REGEXP_UNION:
722
  case kind::REGEXP_INTER:
723
  case kind::REGEXP_STAR:
724
  case kind::REGEXP_PLUS:
725
  case kind::REGEXP_OPT:
726
  case kind::REGEXP_RANGE:
727
  case kind::REGEXP_COMPLEMENT:
728
  case kind::REGEXP_DIFF:
729
  case kind::REGEXP_EMPTY:
730
  case kind::REGEXP_SIGMA:
731
  case kind::SEQ_UNIT:
732
  case kind::SEQ_NTH:
733
5051
  case kind::SEQUENCE_TYPE: out << smtKindString(k, d_variant) << " "; break;
734
4
  case kind::REGEXP_REPEAT:
735
  case kind::REGEXP_LOOP:
736
  {
737
4
    out << n.getOperator() << ' ';
738
4
    stillNeedToPrintParams = false;
739
4
    break;
740
  }
741
742
  case kind::CARDINALITY_CONSTRAINT: out << "fmf.card "; break;
743
  case kind::CARDINALITY_VALUE: out << "fmf.card.val "; break;
744
745
    // bv theory
746
  case kind::BITVECTOR_CONCAT: out << "concat "; forceBinary = true; break;
747
96
  case kind::BITVECTOR_AND: out << "bvand "; forceBinary = true; break;
748
93
  case kind::BITVECTOR_OR: out << "bvor "; forceBinary = true; break;
749
  case kind::BITVECTOR_XOR: out << "bvxor "; forceBinary = true; break;
750
123
  case kind::BITVECTOR_NOT: out << "bvnot "; break;
751
  case kind::BITVECTOR_NAND: out << "bvnand "; break;
752
  case kind::BITVECTOR_NOR: out << "bvnor "; break;
753
  case kind::BITVECTOR_XNOR: out << "bvxnor "; break;
754
  case kind::BITVECTOR_COMP: out << "bvcomp "; break;
755
187
  case kind::BITVECTOR_MULT: out << "bvmul "; forceBinary = true; break;
756
197
  case kind::BITVECTOR_ADD:
757
197
    out << "bvadd ";
758
197
    forceBinary = true;
759
197
    break;
760
  case kind::BITVECTOR_SUB: out << "bvsub "; break;
761
100
  case kind::BITVECTOR_NEG: out << "bvneg "; break;
762
  case kind::BITVECTOR_UDIV: out << "bvudiv "; break;
763
  case kind::BITVECTOR_UREM: out << "bvurem "; break;
764
  case kind::BITVECTOR_SDIV: out << "bvsdiv "; break;
765
  case kind::BITVECTOR_SREM: out << "bvsrem "; break;
766
  case kind::BITVECTOR_SMOD: out << "bvsmod "; break;
767
310
  case kind::BITVECTOR_SHL: out << "bvshl "; break;
768
269
  case kind::BITVECTOR_LSHR: out << "bvlshr "; break;
769
  case kind::BITVECTOR_ASHR: out << "bvashr "; break;
770
2
  case kind::BITVECTOR_ULT: out << "bvult "; break;
771
  case kind::BITVECTOR_ULE: out << "bvule "; break;
772
  case kind::BITVECTOR_UGT: out << "bvugt "; break;
773
  case kind::BITVECTOR_UGE: out << "bvuge "; break;
774
  case kind::BITVECTOR_SLT: out << "bvslt "; break;
775
  case kind::BITVECTOR_SLE: out << "bvsle "; break;
776
  case kind::BITVECTOR_SGT: out << "bvsgt "; break;
777
  case kind::BITVECTOR_SGE: out << "bvsge "; break;
778
35
  case kind::BITVECTOR_TO_NAT: out << "bv2nat "; break;
779
  case kind::BITVECTOR_REDOR: out << "bvredor "; break;
780
  case kind::BITVECTOR_REDAND: out << "bvredand "; break;
781
782
44
  case kind::BITVECTOR_EXTRACT:
783
  case kind::BITVECTOR_REPEAT:
784
  case kind::BITVECTOR_ZERO_EXTEND:
785
  case kind::BITVECTOR_SIGN_EXTEND:
786
  case kind::BITVECTOR_ROTATE_LEFT:
787
  case kind::BITVECTOR_ROTATE_RIGHT:
788
  case kind::INT_TO_BITVECTOR:
789
44
    toStream(out, n.getOperator(), toDepth, nullptr);
790
44
    out << ' ';
791
44
    stillNeedToPrintParams = false;
792
44
    break;
793
794
    // sets
795
2
  case kind::UNION:
796
  case kind::INTERSECTION:
797
  case kind::SETMINUS:
798
  case kind::SUBSET:
799
  case kind::CARD:
800
  case kind::JOIN:
801
  case kind::PRODUCT:
802
  case kind::TRANSPOSE:
803
  case kind::TCLOSURE:
804
2
    out << smtKindString(k, d_variant) << " ";
805
2
    break;
806
  case kind::COMPREHENSION: out << smtKindString(k, d_variant) << " "; break;
807
12
  case kind::SINGLETON:
808
  {
809
12
    out << smtKindString(k, d_variant) << " ";
810
24
    TypeNode elemType = n.getType().getSetElementType();
811
12
    toStreamCastToType(
812
        out, n[0], toDepth < 0 ? toDepth : toDepth - 1, elemType);
813
12
    out << ")";
814
12
    return;
815
  }
816
  break;
817
74
  case kind::MEMBER:
818
  case kind::INSERT:
819
  case kind::SET_TYPE:
820
  case kind::COMPLEMENT:
821
  case kind::CHOOSE:
822
74
  case kind::IS_SINGLETON: out << smtKindString(k, d_variant) << " "; break;
823
  case kind::UNIVERSE_SET:out << "(as univset " << n.getType() << ")";break;
824
825
  // bags
826
34
  case kind::BAG_TYPE:
827
  case kind::UNION_MAX:
828
  case kind::UNION_DISJOINT:
829
  case kind::INTERSECTION_MIN:
830
  case kind::DIFFERENCE_SUBTRACT:
831
  case kind::DIFFERENCE_REMOVE:
832
  case kind::SUBBAG:
833
  case kind::BAG_COUNT:
834
  case kind::DUPLICATE_REMOVAL:
835
  case kind::BAG_CARD:
836
  case kind::BAG_CHOOSE:
837
  case kind::BAG_IS_SINGLETON:
838
  case kind::BAG_FROM_SET:
839
34
  case kind::BAG_TO_SET: out << smtKindString(k, d_variant) << " "; break;
840
4
  case kind::MK_BAG:
841
  {
842
    // print (bag (mkBag_op Real) 1 3) as (bag 1.0 3)
843
4
    out << smtKindString(k, d_variant) << " ";
844
8
    TypeNode elemType = n.getType().getBagElementType();
845
4
    toStreamCastToType(
846
        out, n[0], toDepth < 0 ? toDepth : toDepth - 1, elemType);
847
4
    out << " " << n[1] << ")";
848
4
    return;
849
  }
850
851
    // fp theory
852
74
  case kind::FLOATINGPOINT_FP:
853
  case kind::FLOATINGPOINT_EQ:
854
  case kind::FLOATINGPOINT_ABS:
855
  case kind::FLOATINGPOINT_NEG:
856
  case kind::FLOATINGPOINT_PLUS:
857
  case kind::FLOATINGPOINT_SUB:
858
  case kind::FLOATINGPOINT_MULT:
859
  case kind::FLOATINGPOINT_DIV:
860
  case kind::FLOATINGPOINT_FMA:
861
  case kind::FLOATINGPOINT_SQRT:
862
  case kind::FLOATINGPOINT_REM:
863
  case kind::FLOATINGPOINT_RTI:
864
  case kind::FLOATINGPOINT_MIN:
865
  case kind::FLOATINGPOINT_MAX:
866
  case kind::FLOATINGPOINT_LEQ:
867
  case kind::FLOATINGPOINT_LT:
868
  case kind::FLOATINGPOINT_GEQ:
869
  case kind::FLOATINGPOINT_GT:
870
  case kind::FLOATINGPOINT_ISN:
871
  case kind::FLOATINGPOINT_ISSN:
872
  case kind::FLOATINGPOINT_ISZ:
873
  case kind::FLOATINGPOINT_ISINF:
874
  case kind::FLOATINGPOINT_ISNAN:
875
  case kind::FLOATINGPOINT_ISNEG:
876
  case kind::FLOATINGPOINT_ISPOS:
877
  case kind::FLOATINGPOINT_TO_REAL:
878
  case kind::FLOATINGPOINT_COMPONENT_NAN:
879
  case kind::FLOATINGPOINT_COMPONENT_INF:
880
  case kind::FLOATINGPOINT_COMPONENT_ZERO:
881
  case kind::FLOATINGPOINT_COMPONENT_SIGN:
882
  case kind::FLOATINGPOINT_COMPONENT_EXPONENT:
883
  case kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND:
884
  case kind::ROUNDINGMODE_BITBLAST:
885
74
    out << smtKindString(k, d_variant) << ' ';
886
74
    break;
887
888
2
  case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
889
  case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT:
890
  case kind::FLOATINGPOINT_TO_FP_REAL:
891
  case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
892
  case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
893
  case kind::FLOATINGPOINT_TO_FP_GENERIC:
894
  case kind::FLOATINGPOINT_TO_UBV:
895
  case kind::FLOATINGPOINT_TO_SBV:
896
2
    out << n.getOperator() << ' ';
897
2
    stillNeedToPrintParams = false;
898
2
    break;
899
900
5840
  case kind::APPLY_CONSTRUCTOR:
901
  {
902
5840
    const DType& dt = DType::datatypeOf(n.getOperator());
903
5840
    if (dt.isTuple())
904
    {
905
28
      stillNeedToPrintParams = false;
906
28
      out << "mkTuple" << ( dt[0].getNumArgs()==0 ? "" : " ");
907
    }
908
5840
    break;
909
  }
910
6
  case kind::TUPLE_PROJECT:
911
  {
912
12
    TupleProjectOp op = n.getOperator().getConst<TupleProjectOp>();
913
6
    if (op.getIndices().empty())
914
    {
915
      // e.g. (tuple_project tuple)
916
      out << "project " << n[0] << ")";
917
    }
918
    else
919
    {
920
      // e.g. ((_ tuple_project 2 4 4) tuple)
921
6
      out << "(_ tuple_project" << op << ") " << n[0] << ")";
922
    }
923
6
    return;
924
  }
925
12
  case kind::CONSTRUCTOR_TYPE:
926
  {
927
12
    out << n[n.getNumChildren()-1];
928
12
    return;
929
    break;
930
  }
931
1186
  case kind::APPLY_TESTER:
932
  case kind::APPLY_SELECTOR:
933
  case kind::APPLY_SELECTOR_TOTAL:
934
  case kind::APPLY_UPDATER:
935
1186
  case kind::PARAMETRIC_DATATYPE: break;
936
937
  // separation logic
938
3
  case kind::SEP_EMP:
939
  case kind::SEP_PTO:
940
  case kind::SEP_STAR:
941
3
  case kind::SEP_WAND: out << smtKindString(k, d_variant) << " "; break;
942
943
90
  case kind::SEP_NIL:
944
90
    out << "(as sep.nil " << n.getType() << ")";
945
90
    break;
946
947
    // quantifiers
948
53
  case kind::FORALL:
949
  case kind::EXISTS:
950
  case kind::LAMBDA:
951
  case kind::WITNESS:
952
  {
953
53
    out << smtKindString(k, d_variant) << " ";
954
    // do not letify the bound variable list
955
53
    toStream(out, n[0], toDepth, nullptr);
956
53
    out << " ";
957
106
    std::stringstream annot;
958
53
    if (n.getNumChildren() == 3)
959
    {
960
2
      annot << " ";
961
4
      for (const Node& nc : n[2])
962
      {
963
2
        if (nc.getKind() == kind::INST_PATTERN)
964
        {
965
          out << "(! ";
966
          annot << ":pattern ";
967
          toStream(annot, nc, toDepth, nullptr);
968
          annot << ") ";
969
        }
970
2
        else if (nc.getKind() == kind::INST_NO_PATTERN)
971
        {
972
          out << "(! ";
973
          annot << ":no-pattern ";
974
          toStream(annot, nc, toDepth, nullptr);
975
          annot << ") ";
976
        }
977
      }
978
    }
979
    // Use a fresh let binder, since using existing let symbols may violate
980
    // scoping issues for let-bound variables, see explanation in let_binding.h.
981
53
    size_t dag = lbind == nullptr ? 0 : lbind->getThreshold()-1;
982
53
    toStream(out, n[1], toDepth - 1, dag);
983
53
    out << annot.str() << ")";
984
53
    return;
985
    break;
986
  }
987
848
  case kind::BOUND_VAR_LIST:
988
  {
989
    // the left parenthesis is already printed (before the switch)
990
2738
    for (TNode::iterator i = n.begin(), iend = n.end(); i != iend;)
991
    {
992
1890
      out << '(';
993
1890
      toStream(out, *i, toDepth < 0 ? toDepth : toDepth - 1);
994
1890
      out << ' ';
995
1890
      out << (*i).getType();
996
1890
      out << ')';
997
1890
      if (++i != iend)
998
      {
999
1042
        out << ' ';
1000
      }
1001
    }
1002
848
    out << ')';
1003
848
    return;
1004
  }
1005
  case kind::INST_PATTERN:
1006
  case kind::INST_NO_PATTERN:
1007
  case kind::INST_PATTERN_LIST: break;
1008
383
  default:
1009
    // fall back on however the kind prints itself; this probably
1010
    // won't be SMT-LIB v2 compliant, but it will be clear from the
1011
    // output that support for the kind needs to be added here.
1012
383
    out << n.getKind() << ' ';
1013
  }
1014
619042
  if( n.getMetaKind() == kind::metakind::PARAMETERIZED &&
1015
      stillNeedToPrintParams ) {
1016
50026
    if(toDepth != 0) {
1017
50026
      if (n.getKind() == kind::APPLY_TESTER)
1018
      {
1019
        unsigned cindex = DType::indexOf(n.getOperator());
1020
        const DType& dt = DType::datatypeOf(n.getOperator());
1021
        out << "(_ is ";
1022
        toStream(out,
1023
                 dt[cindex].getConstructor(),
1024
                 toDepth < 0 ? toDepth : toDepth - 1);
1025
        out << ")";
1026
      }else{
1027
100052
        toStream(
1028
100052
            out, n.getOperator(), toDepth < 0 ? toDepth : toDepth - 1, lbind);
1029
      }
1030
    } else {
1031
      out << "(...)";
1032
    }
1033
50026
    if(n.getNumChildren() > 0) {
1034
49701
      out << ' ';
1035
    }
1036
  }
1037
1238084
  stringstream parens;
1038
1039
2014784
  for(size_t i = 0, c = 1; i < n.getNumChildren(); ) {
1040
1395742
    if(toDepth != 0) {
1041
1395742
      toStream(out, n[i], toDepth < 0 ? toDepth : toDepth - c, lbind);
1042
    } else {
1043
      out << "(...)";
1044
    }
1045
1395742
    if(++i < n.getNumChildren()) {
1046
777631
      if(forceBinary && i < n.getNumChildren() - 1) {
1047
        // not going to work properly for parameterized kinds!
1048
        Assert(n.getMetaKind() != kind::metakind::PARAMETERIZED);
1049
        out << " (" << smtKindString(n.getKind(), d_variant) << ' ';
1050
        parens << ')';
1051
        ++c;
1052
      } else {
1053
777631
        out << ' ';
1054
      }
1055
    }
1056
  }
1057
619042
  if (n.getNumChildren() != 0)
1058
  {
1059
618111
    out << parens.str() << ')';
1060
  }
1061
}
1062
1063
40
void Smt2Printer::toStreamCastToType(std::ostream& out,
1064
                                     TNode n,
1065
                                     int toDepth,
1066
                                     TypeNode tn) const
1067
{
1068
80
  Node nasc;
1069
40
  if (n.getType().isInteger() && !tn.isInteger())
1070
  {
1071
2
    Assert(tn.isReal());
1072
    // probably due to subtyping integers and reals, cast it
1073
2
    nasc = NodeManager::currentNM()->mkNode(kind::CAST_TO_REAL, n);
1074
  }
1075
  else
1076
  {
1077
38
    nasc = n;
1078
  }
1079
40
  toStream(out, nasc, toDepth);
1080
40
}
1081
1082
199307
std::string Smt2Printer::smtKindString(Kind k, Variant v)
1083
{
1084
199307
  switch(k) {
1085
    // builtin theory
1086
40731
  case kind::EQUAL: return "=";
1087
4
  case kind::DISTINCT: return "distinct";
1088
  case kind::SEXPR: break;
1089
1090
    // bool theory
1091
23364
  case kind::NOT: return "not";
1092
241
  case kind::AND: return "and";
1093
7
  case kind::IMPLIES: return "=>";
1094
53
  case kind::OR: return "or";
1095
20
  case kind::XOR: return "xor";
1096
4
  case kind::ITE: return "ite";
1097
1098
    // uf theory
1099
  case kind::APPLY_UF: break;
1100
1101
15
  case kind::LAMBDA: return "lambda";
1102
  case kind::MATCH: return "match";
1103
2
  case kind::WITNESS: return "witness";
1104
1105
  // arith theory
1106
40393
  case kind::PLUS: return "+";
1107
36084
  case kind::MULT:
1108
36084
  case kind::NONLINEAR_MULT: return "*";
1109
  case kind::IAND: return "iand";
1110
32
  case kind::EXPONENTIAL: return "exp";
1111
264
  case kind::SINE: return "sin";
1112
  case kind::COSINE: return "cos";
1113
  case kind::TANGENT: return "tan";
1114
  case kind::COSECANT: return "csc";
1115
  case kind::SECANT: return "sec";
1116
  case kind::COTANGENT: return "cot";
1117
  case kind::ARCSINE: return "arcsin";
1118
  case kind::ARCCOSINE: return "arccos";
1119
  case kind::ARCTANGENT: return "arctan";
1120
  case kind::ARCCOSECANT: return "arccsc";
1121
  case kind::ARCSECANT: return "arcsec";
1122
  case kind::ARCCOTANGENT: return "arccot";
1123
300
  case kind::PI: return "real.pi";
1124
  case kind::SQRT: return "sqrt";
1125
6
  case kind::MINUS: return "-";
1126
2
  case kind::UMINUS: return "-";
1127
19054
  case kind::LT: return "<";
1128
72
  case kind::LEQ: return "<=";
1129
2280
  case kind::GT: return ">";
1130
30604
  case kind::GEQ: return ">=";
1131
5
  case kind::DIVISION:
1132
5
  case kind::DIVISION_TOTAL: return "/";
1133
3
  case kind::INTS_DIVISION_TOTAL:
1134
3
  case kind::INTS_DIVISION: return "div";
1135
1
  case kind::INTS_MODULUS_TOTAL:
1136
1
  case kind::INTS_MODULUS: return "mod";
1137
  case kind::ABS: return "abs";
1138
  case kind::IS_INTEGER: return "is_int";
1139
  case kind::TO_INTEGER: return "to_int";
1140
  case kind::TO_REAL: return "to_real";
1141
  case kind::POW: return "^";
1142
1143
    // arrays theory
1144
253
  case kind::SELECT: return "select";
1145
  case kind::STORE: return "store";
1146
217
  case kind::ARRAY_TYPE: return "Array";
1147
  case kind::PARTIAL_SELECT_0: return "partial_select_0";
1148
  case kind::PARTIAL_SELECT_1: return "partial_select_1";
1149
  case kind::EQ_RANGE:
1150
    return "eqrange";
1151
1152
    // bv theory
1153
  case kind::BITVECTOR_CONCAT: return "concat";
1154
  case kind::BITVECTOR_AND: return "bvand";
1155
  case kind::BITVECTOR_OR: return "bvor";
1156
  case kind::BITVECTOR_XOR: return "bvxor";
1157
  case kind::BITVECTOR_NOT: return "bvnot";
1158
  case kind::BITVECTOR_NAND: return "bvnand";
1159
  case kind::BITVECTOR_NOR: return "bvnor";
1160
  case kind::BITVECTOR_XNOR: return "bvxnor";
1161
  case kind::BITVECTOR_COMP: return "bvcomp";
1162
  case kind::BITVECTOR_MULT: return "bvmul";
1163
  case kind::BITVECTOR_ADD: return "bvadd";
1164
  case kind::BITVECTOR_SUB: return "bvsub";
1165
  case kind::BITVECTOR_NEG: return "bvneg";
1166
  case kind::BITVECTOR_UDIV: return "bvudiv";
1167
  case kind::BITVECTOR_UREM: return "bvurem";
1168
  case kind::BITVECTOR_SDIV: return "bvsdiv";
1169
  case kind::BITVECTOR_SREM: return "bvsrem";
1170
  case kind::BITVECTOR_SMOD: return "bvsmod";
1171
  case kind::BITVECTOR_SHL: return "bvshl";
1172
  case kind::BITVECTOR_LSHR: return "bvlshr";
1173
  case kind::BITVECTOR_ASHR: return "bvashr";
1174
  case kind::BITVECTOR_ULT: return "bvult";
1175
  case kind::BITVECTOR_ULE: return "bvule";
1176
  case kind::BITVECTOR_UGT: return "bvugt";
1177
  case kind::BITVECTOR_UGE: return "bvuge";
1178
  case kind::BITVECTOR_SLT: return "bvslt";
1179
  case kind::BITVECTOR_SLE: return "bvsle";
1180
  case kind::BITVECTOR_SGT: return "bvsgt";
1181
  case kind::BITVECTOR_SGE: return "bvsge";
1182
  case kind::BITVECTOR_TO_NAT: return "bv2nat";
1183
  case kind::BITVECTOR_REDOR: return "bvredor";
1184
  case kind::BITVECTOR_REDAND: return "bvredand";
1185
1186
  case kind::BITVECTOR_EXTRACT: return "extract";
1187
  case kind::BITVECTOR_REPEAT: return "repeat";
1188
  case kind::BITVECTOR_ZERO_EXTEND: return "zero_extend";
1189
  case kind::BITVECTOR_SIGN_EXTEND: return "sign_extend";
1190
  case kind::BITVECTOR_ROTATE_LEFT: return "rotate_left";
1191
  case kind::BITVECTOR_ROTATE_RIGHT: return "rotate_right";
1192
  case kind::INT_TO_BITVECTOR: return "int2bv";
1193
1194
  case kind::UNION: return "union";
1195
  case kind::INTERSECTION: return "intersection";
1196
  case kind::SETMINUS: return "setminus";
1197
  case kind::SUBSET: return "subset";
1198
  case kind::MEMBER: return "member";
1199
74
  case kind::SET_TYPE: return "Set";
1200
12
  case kind::SINGLETON: return "singleton";
1201
  case kind::INSERT: return "insert";
1202
  case kind::COMPLEMENT: return "complement";
1203
2
  case kind::CARD: return "card";
1204
  case kind::COMPREHENSION: return "comprehension";
1205
  case kind::CHOOSE: return "choose";
1206
  case kind::IS_SINGLETON: return "is_singleton";
1207
  case kind::JOIN: return "join";
1208
  case kind::PRODUCT: return "product";
1209
  case kind::TRANSPOSE: return "transpose";
1210
  case kind::TCLOSURE: return "tclosure";
1211
1212
  // bag theory
1213
2
  case kind::BAG_TYPE: return "Bag";
1214
  case kind::UNION_MAX: return "union_max";
1215
  case kind::UNION_DISJOINT: return "union_disjoint";
1216
  case kind::INTERSECTION_MIN: return "intersection_min";
1217
  case kind::DIFFERENCE_SUBTRACT: return "difference_subtract";
1218
  case kind::DIFFERENCE_REMOVE: return "difference_remove";
1219
  case kind::SUBBAG: return "subbag";
1220
26
  case kind::BAG_COUNT: return "bag.count";
1221
6
  case kind::DUPLICATE_REMOVAL: return "duplicate_removal";
1222
4
  case kind::MK_BAG: return "bag";
1223
  case kind::BAG_CARD: return "bag.card";
1224
  case kind::BAG_CHOOSE: return "bag.choose";
1225
  case kind::BAG_IS_SINGLETON: return "bag.is_singleton";
1226
  case kind::BAG_FROM_SET: return "bag.from_set";
1227
  case kind::BAG_TO_SET: return "bag.to_set";
1228
1229
    // fp theory
1230
  case kind::FLOATINGPOINT_FP: return "fp";
1231
  case kind::FLOATINGPOINT_EQ: return "fp.eq";
1232
1
  case kind::FLOATINGPOINT_ABS: return "fp.abs";
1233
2
  case kind::FLOATINGPOINT_NEG: return "fp.neg";
1234
6
  case kind::FLOATINGPOINT_PLUS: return "fp.add";
1235
13
  case kind::FLOATINGPOINT_SUB: return "fp.sub";
1236
10
  case kind::FLOATINGPOINT_MULT: return "fp.mul";
1237
19
  case kind::FLOATINGPOINT_DIV: return "fp.div";
1238
  case kind::FLOATINGPOINT_FMA: return "fp.fma";
1239
2
  case kind::FLOATINGPOINT_SQRT: return "fp.sqrt";
1240
15
  case kind::FLOATINGPOINT_REM: return "fp.rem";
1241
  case kind::FLOATINGPOINT_RTI: return "fp.roundToIntegral";
1242
  case kind::FLOATINGPOINT_MIN: return "fp.min";
1243
  case kind::FLOATINGPOINT_MAX: return "fp.max";
1244
  case kind::FLOATINGPOINT_MIN_TOTAL: return "fp.min_total";
1245
  case kind::FLOATINGPOINT_MAX_TOTAL: return "fp.max_total";
1246
1247
  case kind::FLOATINGPOINT_LEQ: return "fp.leq";
1248
  case kind::FLOATINGPOINT_LT: return "fp.lt";
1249
  case kind::FLOATINGPOINT_GEQ: return "fp.geq";
1250
  case kind::FLOATINGPOINT_GT: return "fp.gt";
1251
1252
1
  case kind::FLOATINGPOINT_ISN: return "fp.isNormal";
1253
1
  case kind::FLOATINGPOINT_ISSN: return "fp.isSubnormal";
1254
1
  case kind::FLOATINGPOINT_ISZ: return "fp.isZero";
1255
  case kind::FLOATINGPOINT_ISINF: return "fp.isInfinite";
1256
1
  case kind::FLOATINGPOINT_ISNAN: return "fp.isNaN";
1257
1
  case kind::FLOATINGPOINT_ISNEG: return "fp.isNegative";
1258
1
  case kind::FLOATINGPOINT_ISPOS: return "fp.isPositive";
1259
1260
  case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR: return "to_fp";
1261
  case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT: return "to_fp";
1262
  case kind::FLOATINGPOINT_TO_FP_REAL: return "to_fp";
1263
  case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR: return "to_fp";
1264
  case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR: return "to_fp_unsigned";
1265
  case kind::FLOATINGPOINT_TO_FP_GENERIC: return "to_fp_unsigned";
1266
  case kind::FLOATINGPOINT_TO_UBV: return "fp.to_ubv";
1267
  case kind::FLOATINGPOINT_TO_UBV_TOTAL: return "fp.to_ubv_total";
1268
  case kind::FLOATINGPOINT_TO_SBV: return "fp.to_sbv";
1269
  case kind::FLOATINGPOINT_TO_SBV_TOTAL: return "fp.to_sbv_total";
1270
  case kind::FLOATINGPOINT_TO_REAL: return "fp.to_real";
1271
  case kind::FLOATINGPOINT_TO_REAL_TOTAL: return "fp.to_real_total";
1272
1273
  case kind::FLOATINGPOINT_COMPONENT_NAN: return "NAN";
1274
  case kind::FLOATINGPOINT_COMPONENT_INF: return "INF";
1275
  case kind::FLOATINGPOINT_COMPONENT_ZERO: return "ZERO";
1276
  case kind::FLOATINGPOINT_COMPONENT_SIGN: return "SIGN";
1277
  case kind::FLOATINGPOINT_COMPONENT_EXPONENT: return "EXPONENT";
1278
  case kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND: return "SIGNIFICAND";
1279
  case kind::ROUNDINGMODE_BITBLAST:
1280
    return "RMBITBLAST";
1281
1282
  //string theory
1283
  case kind::STRING_CONCAT: return "str.++";
1284
2081
  case kind::STRING_LENGTH: return "str.len";
1285
461
  case kind::STRING_SUBSTR: return "str.substr" ;
1286
  case kind::STRING_UPDATE: return "str.update";
1287
128
  case kind::STRING_STRCTN: return "str.contains" ;
1288
16
  case kind::STRING_CHARAT: return "str.at" ;
1289
121
  case kind::STRING_STRIDOF: return "str.indexof" ;
1290
707
  case kind::STRING_STRREPL: return "str.replace" ;
1291
  case kind::STRING_STRREPLALL: return "str.replace_all";
1292
12
  case kind::STRING_REPLACE_RE: return "str.replace_re";
1293
12
  case kind::STRING_REPLACE_RE_ALL: return "str.replace_re_all";
1294
  case kind::STRING_TOLOWER: return "str.tolower";
1295
  case kind::STRING_TOUPPER: return "str.toupper";
1296
  case kind::STRING_REV: return "str.rev";
1297
4
  case kind::STRING_PREFIX: return "str.prefixof" ;
1298
4
  case kind::STRING_SUFFIX: return "str.suffixof" ;
1299
  case kind::STRING_LEQ: return "str.<=";
1300
  case kind::STRING_LT: return "str.<";
1301
2
  case kind::STRING_FROM_CODE: return "str.from_code";
1302
793
  case kind::STRING_TO_CODE: return "str.to_code";
1303
25
  case kind::STRING_ITOS: return "str.from_int";
1304
  case kind::STRING_STOI: return "str.to_int";
1305
6
  case kind::STRING_IN_REGEXP: return "str.in_re";
1306
196
  case kind::STRING_TO_REGEXP: return "str.to_re";
1307
  case kind::REGEXP_EMPTY: return "re.none";
1308
216
  case kind::REGEXP_SIGMA: return "re.allchar";
1309
126
  case kind::REGEXP_CONCAT: return "re.++";
1310
4
  case kind::REGEXP_UNION: return "re.union";
1311
  case kind::REGEXP_INTER: return "re.inter";
1312
114
  case kind::REGEXP_STAR: return "re.*";
1313
  case kind::REGEXP_PLUS: return "re.+";
1314
  case kind::REGEXP_OPT: return "re.opt";
1315
  case kind::REGEXP_RANGE: return "re.range";
1316
  case kind::REGEXP_REPEAT: return "re.^";
1317
  case kind::REGEXP_LOOP: return "re.loop";
1318
  case kind::REGEXP_COMPLEMENT: return "re.comp";
1319
  case kind::REGEXP_DIFF: return "re.diff";
1320
13
  case kind::SEQUENCE_TYPE: return "Seq";
1321
2
  case kind::SEQ_UNIT: return "seq.unit";
1322
14
  case kind::SEQ_NTH: return "seq.nth";
1323
1324
  //sep theory
1325
  case kind::SEP_STAR: return "sep";
1326
  case kind::SEP_PTO: return "pto";
1327
1
  case kind::SEP_WAND: return "wand";
1328
2
  case kind::SEP_EMP: return "emp";
1329
1330
  // quantifiers
1331
34
  case kind::FORALL: return "forall";
1332
2
  case kind::EXISTS: return "exists";
1333
1334
  default:
1335
    ; /* fall through */
1336
  }
1337
1338
  // no SMT way to print these
1339
  return kind::kindToString(k);
1340
}
1341
1342
42
void Smt2Printer::toStreamType(std::ostream& out, TypeNode tn) const
1343
{
1344
  // we currently must call TypeNode::toStream here.
1345
42
  tn.toStream(out, language::output::LANG_SMTLIB_V2_6);
1346
42
}
1347
1348
template <class T>
1349
static bool tryToStream(std::ostream& out, const Command* c);
1350
template <class T>
1351
static bool tryToStream(std::ostream& out, const Command* c, Variant v);
1352
1353
2
static std::string quoteSymbol(TNode n) {
1354
4
  std::stringstream ss;
1355
2
  ss << n;
1356
4
  return cvc5::quoteSymbol(ss.str());
1357
}
1358
1359
template <class T>
1360
static bool tryToStream(std::ostream& out, const CommandStatus* s, Variant v);
1361
1362
266792
void Smt2Printer::toStream(std::ostream& out, const CommandStatus* s) const
1363
{
1364
533630
  if (tryToStream<CommandSuccess>(out, s, d_variant) ||
1365
61
      tryToStream<CommandFailure>(out, s, d_variant) ||
1366
15
      tryToStream<CommandRecoverableFailure>(out, s, d_variant) ||
1367
266792
      tryToStream<CommandUnsupported>(out, s, d_variant) ||
1368
      tryToStream<CommandInterrupted>(out, s, d_variant)) {
1369
266792
    return;
1370
  }
1371
1372
  out << "ERROR: don't know how to print a CommandStatus of class: "
1373
      << typeid(*s).name() << endl;
1374
1375
}/* Smt2Printer::toStream(CommandStatus*) */
1376
1377
10
void Smt2Printer::toStream(std::ostream& out, const UnsatCore& core) const
1378
{
1379
10
  out << "(" << std::endl;
1380
10
  if (core.useNames())
1381
  {
1382
    // use the names
1383
7
    const std::vector<std::string>& cnames = core.getCoreNames();
1384
24
    for (const std::string& cn : cnames)
1385
    {
1386
17
      out << cvc5::quoteSymbol(cn) << std::endl;
1387
    }
1388
  }
1389
  else
1390
  {
1391
    // otherwise, use the formulas
1392
6
    for (UnsatCore::const_iterator i = core.begin(); i != core.end(); ++i)
1393
    {
1394
3
      out << *i << endl;
1395
    }
1396
  }
1397
10
  out << ")" << endl;
1398
10
}/* Smt2Printer::toStream(UnsatCore, map<Expr, string>) */
1399
1400
21
void Smt2Printer::toStream(std::ostream& out, const smt::Model& m) const
1401
{
1402
21
  const theory::TheoryModel* tm = m.getTheoryModel();
1403
  //print the model comments
1404
42
  std::stringstream c;
1405
21
  tm->getComments(c);
1406
42
  std::string ln;
1407
21
  while( std::getline( c, ln ) ){
1408
    out << "; " << ln << std::endl;
1409
  }
1410
  //print the model
1411
21
  out << "(" << endl;
1412
  // don't need to print approximations since they are built into choice
1413
  // functions in the values of variables.
1414
21
  this->Printer::toStream(out, m);
1415
21
  out << ")" << endl;
1416
  //print the heap model, if it exists
1417
42
  Node h, neq;
1418
21
  if (tm->getHeapModel(h, neq))
1419
  {
1420
    // description of the heap+what nil is equal to fully describes model
1421
    out << "(heap" << endl;
1422
    out << h << endl;
1423
    out << neq << endl;
1424
    out << ")" << std::endl;
1425
  }
1426
21
}
1427
1428
4
void Smt2Printer::toStreamModelSort(std::ostream& out,
1429
                                    const smt::Model& m,
1430
                                    TypeNode tn) const
1431
{
1432
4
  if (!tn.isSort())
1433
  {
1434
    out << "ERROR: don't know how to print non uninterpreted sort in model: "
1435
        << tn << std::endl;
1436
    return;
1437
  }
1438
4
  const theory::TheoryModel* tm = m.getTheoryModel();
1439
8
  std::vector<Node> elements = tm->getDomainElements(tn);
1440
4
  if (options::modelUninterpPrint() == options::ModelUninterpPrintMode::DtEnum)
1441
  {
1442
    out << "(declare-datatypes ((" << tn << " 0)) (";
1443
    for (const Node& type_ref : elements)
1444
    {
1445
      out << "(" << type_ref << ")";
1446
    }
1447
    out << ")))" << endl;
1448
    return;
1449
  }
1450
  // print the cardinality
1451
4
  out << "; cardinality of " << tn << " is " << elements.size() << endl;
1452
8
  if (options::modelUninterpPrint()
1453
4
      == options::ModelUninterpPrintMode::DeclSortAndFun)
1454
  {
1455
    toStreamCmdDeclareType(out, tn);
1456
  }
1457
  // print the representatives
1458
8
  for (const Node& trn : elements)
1459
  {
1460
4
    if (trn.isVar())
1461
    {
1462
8
      if (options::modelUninterpPrint()
1463
              == options::ModelUninterpPrintMode::DeclSortAndFun
1464
4
          || options::modelUninterpPrint()
1465
                 == options::ModelUninterpPrintMode::DeclFun)
1466
      {
1467
4
        out << "(declare-fun " << quoteSymbol(trn) << " () " << tn << ")"
1468
2
            << endl;
1469
      }
1470
    }
1471
    else
1472
    {
1473
      out << "; rep: " << trn << endl;
1474
    }
1475
  }
1476
}
1477
1478
24
void Smt2Printer::toStreamModelTerm(std::ostream& out,
1479
                                    const smt::Model& m,
1480
                                    Node n) const
1481
{
1482
24
  const theory::TheoryModel* tm = m.getTheoryModel();
1483
  // We get the value from the theory model directly, which notice
1484
  // does not have to go through the standard SmtEngine::getValue interface.
1485
48
  Node val = tm->getValue(n);
1486
24
  if (val.getKind() == kind::LAMBDA)
1487
  {
1488
2
    TypeNode rangeType = n.getType().getRangeType();
1489
1
    out << "(define-fun " << n << " " << val[0] << " " << rangeType << " ";
1490
    // call toStream and force its type to be proper
1491
1
    toStreamCastToType(out, val[1], -1, rangeType);
1492
1
    out << ")" << endl;
1493
  }
1494
  else
1495
  {
1496
46
    if (options::modelUninterpPrint() == options::ModelUninterpPrintMode::DtEnum
1497
23
        && val.getKind() == kind::STORE)
1498
    {
1499
      TypeNode tn = val[1].getType();
1500
      const std::vector<Node>* type_refs =
1501
          tm->getRepSet()->getTypeRepsOrNull(tn);
1502
      if (tn.isSort() && type_refs != nullptr)
1503
      {
1504
        Cardinality indexCard(type_refs->size());
1505
        val = theory::arrays::TheoryArraysRewriter::normalizeConstant(
1506
            val, indexCard);
1507
      }
1508
    }
1509
23
    out << "(define-fun " << n << " () " << n.getType() << " ";
1510
    // call toStream and force its type to be proper
1511
23
    toStreamCastToType(out, val, -1, n.getType());
1512
23
    out << ")" << endl;
1513
  }
1514
24
}
1515
1516
7
void Smt2Printer::toStreamCmdAssert(std::ostream& out, Node n) const
1517
{
1518
7
  out << "(assert " << n << ')' << std::endl;
1519
7
}
1520
1521
void Smt2Printer::toStreamCmdPush(std::ostream& out) const
1522
{
1523
  out << "(push 1)" << std::endl;
1524
}
1525
1526
void Smt2Printer::toStreamCmdPop(std::ostream& out) const
1527
{
1528
  out << "(pop 1)" << std::endl;
1529
}
1530
1531
2
void Smt2Printer::toStreamCmdCheckSat(std::ostream& out, Node n) const
1532
{
1533
2
  if (!n.isNull())
1534
  {
1535
    toStreamCmdPush(out);
1536
    out << std::endl;
1537
    toStreamCmdAssert(out, n);
1538
    out << std::endl;
1539
    toStreamCmdCheckSat(out);
1540
    out << std::endl;
1541
    toStreamCmdPop(out);
1542
  }
1543
  else
1544
  {
1545
2
    out << "(check-sat)";
1546
  }
1547
2
  out << std::endl;
1548
2
}
1549
1550
void Smt2Printer::toStreamCmdCheckSatAssuming(
1551
    std::ostream& out, const std::vector<Node>& nodes) const
1552
{
1553
  out << "(check-sat-assuming ( ";
1554
  copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, " "));
1555
  out << "))" << std::endl;
1556
}
1557
1558
void Smt2Printer::toStreamCmdQuery(std::ostream& out, Node n) const
1559
{
1560
  if (!n.isNull())
1561
  {
1562
    toStreamCmdCheckSatAssuming(out, {n});
1563
  }
1564
  else
1565
  {
1566
    toStreamCmdCheckSat(out);
1567
  }
1568
}
1569
1570
void Smt2Printer::toStreamCmdReset(std::ostream& out) const
1571
{
1572
  out << "(reset)" << std::endl;
1573
}
1574
1575
void Smt2Printer::toStreamCmdResetAssertions(std::ostream& out) const
1576
{
1577
  out << "(reset-assertions)" << std::endl;
1578
}
1579
1580
void Smt2Printer::toStreamCmdQuit(std::ostream& out) const
1581
{
1582
  out << "(exit)" << std::endl;
1583
}
1584
1585
void Smt2Printer::toStreamCmdCommandSequence(
1586
    std::ostream& out, const std::vector<Command*>& sequence) const
1587
{
1588
  for (Command* i : sequence)
1589
  {
1590
    out << *i;
1591
  }
1592
}
1593
1594
void Smt2Printer::toStreamCmdDeclarationSequence(
1595
    std::ostream& out, const std::vector<Command*>& sequence) const
1596
{
1597
  toStreamCmdCommandSequence(out, sequence);
1598
}
1599
1600
10
void Smt2Printer::toStreamCmdDeclareFunction(std::ostream& out,
1601
                                             const std::string& id,
1602
                                             TypeNode type) const
1603
{
1604
10
  out << "(declare-fun " << cvc5::quoteSymbol(id) << " (";
1605
10
  if (type.isFunction())
1606
  {
1607
    const vector<TypeNode> argTypes = type.getArgTypes();
1608
    if (argTypes.size() > 0)
1609
    {
1610
      copy(argTypes.begin(),
1611
           argTypes.end() - 1,
1612
           ostream_iterator<TypeNode>(out, " "));
1613
      out << argTypes.back();
1614
    }
1615
    type = type.getRangeType();
1616
  }
1617
1618
10
  out << ") " << type << ')' << std::endl;
1619
10
}
1620
1621
7
void Smt2Printer::toStreamCmdDefineFunction(std::ostream& out,
1622
                                            const std::string& id,
1623
                                            const std::vector<Node>& formals,
1624
                                            TypeNode range,
1625
                                            Node formula) const
1626
{
1627
7
  out << "(define-fun " << id << " (";
1628
7
  if (!formals.empty())
1629
  {
1630
6
    vector<Node>::const_iterator i = formals.cbegin();
1631
    for (;;)
1632
    {
1633
12
      out << "(" << (*i) << " " << (*i).getType() << ")";
1634
9
      ++i;
1635
9
      if (i != formals.cend())
1636
      {
1637
3
        out << " ";
1638
      }
1639
      else
1640
      {
1641
6
        break;
1642
      }
1643
    }
1644
  }
1645
7
  out << ") " << range << ' ' << formula << ')' << std::endl;
1646
7
}
1647
1648
void Smt2Printer::toStreamCmdDefineFunctionRec(
1649
    std::ostream& out,
1650
    const std::vector<Node>& funcs,
1651
    const std::vector<std::vector<Node>>& formals,
1652
    const std::vector<Node>& formulas) const
1653
{
1654
  out << "(define-fun";
1655
  if (funcs.size() > 1)
1656
  {
1657
    out << "s";
1658
  }
1659
  out << "-rec ";
1660
  if (funcs.size() > 1)
1661
  {
1662
    out << "(";
1663
  }
1664
  for (unsigned i = 0, size = funcs.size(); i < size; i++)
1665
  {
1666
    if (funcs.size() > 1)
1667
    {
1668
      if (i > 0)
1669
      {
1670
        out << " ";
1671
      }
1672
      out << "(";
1673
    }
1674
    out << funcs[i] << " (";
1675
    // print its type signature
1676
    vector<Node>::const_iterator itf = formals[i].cbegin();
1677
    for (;;)
1678
    {
1679
      out << "(" << (*itf) << " " << (*itf).getType() << ")";
1680
      ++itf;
1681
      if (itf != formals[i].end())
1682
      {
1683
        out << " ";
1684
      }
1685
      else
1686
      {
1687
        break;
1688
      }
1689
    }
1690
    TypeNode type = funcs[i].getType();
1691
    type = type.getRangeType();
1692
    out << ") " << type;
1693
    if (funcs.size() > 1)
1694
    {
1695
      out << ")";
1696
    }
1697
  }
1698
  if (funcs.size() > 1)
1699
  {
1700
    out << ") (";
1701
  }
1702
  for (unsigned i = 0, size = formulas.size(); i < size; i++)
1703
  {
1704
    if (i > 0)
1705
    {
1706
      out << " ";
1707
    }
1708
    out << formulas[i];
1709
  }
1710
  if (funcs.size() > 1)
1711
  {
1712
    out << ")";
1713
  }
1714
  out << ")" << std::endl;
1715
}
1716
1717
void Smt2Printer::toStreamCmdDeclareType(std::ostream& out,
1718
                                         TypeNode type) const
1719
{
1720
  Assert(type.isSort() || type.isSortConstructor());
1721
  std::stringstream id;
1722
  id << type;
1723
  size_t arity = type.isSortConstructor() ? type.getSortConstructorArity() : 0;
1724
  out << "(declare-sort " << cvc5::quoteSymbol(id.str()) << " " << arity << ")"
1725
      << std::endl;
1726
}
1727
1728
void Smt2Printer::toStreamCmdDefineType(std::ostream& out,
1729
                                        const std::string& id,
1730
                                        const std::vector<TypeNode>& params,
1731
                                        TypeNode t) const
1732
{
1733
  out << "(define-sort " << cvc5::quoteSymbol(id) << " (";
1734
  if (params.size() > 0)
1735
  {
1736
    copy(
1737
        params.begin(), params.end() - 1, ostream_iterator<TypeNode>(out, " "));
1738
    out << params.back();
1739
  }
1740
  out << ") " << t << ")" << std::endl;
1741
}
1742
1743
void Smt2Printer::toStreamCmdSimplify(std::ostream& out, Node n) const
1744
{
1745
  out << "(simplify " << n << ')' << std::endl;
1746
}
1747
1748
void Smt2Printer::toStreamCmdGetValue(std::ostream& out,
1749
                                      const std::vector<Node>& nodes) const
1750
{
1751
  out << "(get-value ( ";
1752
  copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, " "));
1753
  out << "))" << std::endl;
1754
}
1755
1756
void Smt2Printer::toStreamCmdGetModel(std::ostream& out) const
1757
{
1758
  out << "(get-model)" << std::endl;
1759
}
1760
1761
void Smt2Printer::toStreamCmdGetAssignment(std::ostream& out) const
1762
{
1763
  out << "(get-assignment)" << std::endl;
1764
}
1765
1766
void Smt2Printer::toStreamCmdGetAssertions(std::ostream& out) const
1767
{
1768
  out << "(get-assertions)" << std::endl;
1769
}
1770
1771
void Smt2Printer::toStreamCmdGetProof(std::ostream& out) const
1772
{
1773
  out << "(get-proof)" << std::endl;
1774
}
1775
1776
void Smt2Printer::toStreamCmdGetUnsatAssumptions(std::ostream& out) const
1777
{
1778
  out << "(get-unsat-assumptions)" << std::endl;
1779
}
1780
1781
void Smt2Printer::toStreamCmdGetUnsatCore(std::ostream& out) const
1782
{
1783
  out << "(get-unsat-core)" << std::endl;
1784
}
1785
1786
void Smt2Printer::toStreamCmdSetBenchmarkStatus(std::ostream& out,
1787
                                                Result::Sat status) const
1788
{
1789
  out << "(set-info :status " << status << ')' << std::endl;
1790
}
1791
1792
2
void Smt2Printer::toStreamCmdSetBenchmarkLogic(std::ostream& out,
1793
                                               const std::string& logic) const
1794
{
1795
2
  out << "(set-logic " << logic << ')' << std::endl;
1796
2
}
1797
1798
void Smt2Printer::toStreamCmdSetInfo(std::ostream& out,
1799
                                     const std::string& flag,
1800
                                     const std::string& value) const
1801
{
1802
  out << "(set-info :" << flag << ' ' << value << ')' << std::endl;
1803
}
1804
1805
11
void Smt2Printer::toStreamCmdGetInfo(std::ostream& out,
1806
                                     const std::string& flag) const
1807
{
1808
11
  out << "(get-info :" << flag << ')' << std::endl;
1809
11
}
1810
1811
3
void Smt2Printer::toStreamCmdSetOption(std::ostream& out,
1812
                                       const std::string& flag,
1813
                                       const std::string& value) const
1814
{
1815
3
  out << "(set-option :" << flag << ' ' << value << ')' << std::endl;
1816
3
}
1817
1818
void Smt2Printer::toStreamCmdGetOption(std::ostream& out,
1819
                                       const std::string& flag) const
1820
{
1821
  out << "(get-option :" << flag << ')' << std::endl;
1822
}
1823
1824
void Smt2Printer::toStream(std::ostream& out, const DType& dt) const
1825
{
1826
  for (size_t i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
1827
  {
1828
    const DTypeConstructor& cons = dt[i];
1829
    if (i != 0)
1830
    {
1831
      out << " ";
1832
    }
1833
    out << "(" << cvc5::quoteSymbol(cons.getName());
1834
    for (size_t j = 0, nargs = cons.getNumArgs(); j < nargs; j++)
1835
    {
1836
      const DTypeSelector& arg = cons[j];
1837
      out << " (" << arg.getSelector() << " " << arg.getRangeType() << ")";
1838
    }
1839
    out << ")";
1840
  }
1841
}
1842
1843
void Smt2Printer::toStreamCmdDatatypeDeclaration(
1844
    std::ostream& out, const std::vector<TypeNode>& datatypes) const
1845
{
1846
  Assert(!datatypes.empty());
1847
  Assert(datatypes[0].isDatatype());
1848
  const DType& d0 = datatypes[0].getDType();
1849
  if (d0.isTuple())
1850
  {
1851
    // not necessary to print tuples
1852
    Assert(datatypes.size() == 1);
1853
    return;
1854
  }
1855
  out << "(declare-";
1856
  if (d0.isCodatatype())
1857
  {
1858
    out << "co";
1859
  }
1860
  out << "datatypes";
1861
  out << " (";
1862
  for (const TypeNode& t : datatypes)
1863
  {
1864
    Assert(t.isDatatype());
1865
    const DType& d = t.getDType();
1866
    out << "(" << cvc5::quoteSymbol(d.getName());
1867
    out << " " << d.getNumParameters() << ")";
1868
  }
1869
  out << ") (";
1870
  for (const TypeNode& t : datatypes)
1871
  {
1872
    Assert(t.isDatatype());
1873
    const DType& d = t.getDType();
1874
    if (d.isParametric())
1875
    {
1876
      out << "(par (";
1877
      for (unsigned p = 0, nparam = d.getNumParameters(); p < nparam; p++)
1878
      {
1879
        out << (p > 0 ? " " : "") << d.getParameter(p);
1880
      }
1881
      out << ")";
1882
    }
1883
    out << "(";
1884
    toStream(out, d);
1885
    out << ")";
1886
    if (d.isParametric())
1887
    {
1888
      out << ")";
1889
    }
1890
  }
1891
  out << ")";
1892
  out << ")" << std::endl;
1893
}
1894
1895
1
void Smt2Printer::toStreamCmdComment(std::ostream& out,
1896
                                     const std::string& comment) const
1897
{
1898
2
  std::string s = comment;
1899
1
  size_t pos = 0;
1900
1
  while ((pos = s.find_first_of('"', pos)) != string::npos)
1901
  {
1902
    s.replace(pos, 1, "\"\"");
1903
    pos += 2;
1904
  }
1905
1
  out << "(set-info :notes \"" << s << "\")" << std::endl;
1906
1
}
1907
1908
void Smt2Printer::toStreamCmdDeclareHeap(std::ostream& out,
1909
                                         TypeNode locType,
1910
                                         TypeNode dataType) const
1911
{
1912
  out << "(declare-heap (" << locType << " " << dataType << "))" << std::endl;
1913
}
1914
1915
void Smt2Printer::toStreamCmdEmpty(std::ostream& out,
1916
                                   const std::string& name) const
1917
{
1918
  out << std::endl;
1919
}
1920
1921
void Smt2Printer::toStreamCmdEcho(std::ostream& out,
1922
                                  const std::string& output) const
1923
{
1924
  std::string s = output;
1925
  // escape all double-quotes
1926
  size_t pos = 0;
1927
  while ((pos = s.find('"', pos)) != string::npos)
1928
  {
1929
    s.replace(pos, 1, "\"\"");
1930
    pos += 2;
1931
  }
1932
  out << "(echo \"" << s << "\")" << std::endl;
1933
}
1934
1935
/*
1936
   --------------------------------------------------------------------------
1937
    Handling SyGuS commands
1938
   --------------------------------------------------------------------------
1939
*/
1940
1941
1
static void toStreamSygusGrammar(std::ostream& out, const TypeNode& t)
1942
{
1943
1
  if (!t.isNull() && t.isDatatype() && t.getDType().isSygus())
1944
  {
1945
2
    std::stringstream types_predecl, types_list;
1946
2
    std::set<TypeNode> grammarTypes;
1947
2
    std::list<TypeNode> typesToPrint;
1948
1
    grammarTypes.insert(t);
1949
1
    typesToPrint.push_back(t);
1950
1
    NodeManager* nm = NodeManager::currentNM();
1951
    // for each datatype in grammar
1952
    //   name
1953
    //   sygus type
1954
    //   constructors in order
1955
    do
1956
    {
1957
2
      TypeNode curr = typesToPrint.front();
1958
1
      typesToPrint.pop_front();
1959
1
      Assert(curr.isDatatype() && curr.getDType().isSygus());
1960
1
      const DType& dt = curr.getDType();
1961
1
      types_list << '(' << dt.getName() << ' ' << dt.getSygusType() << " (";
1962
1
      types_predecl << '(' << dt.getName() << ' ' << dt.getSygusType() << ") ";
1963
1
      if (dt.getSygusAllowConst())
1964
      {
1965
        types_list << "(Constant " << dt.getSygusType() << ") ";
1966
      }
1967
2
      for (size_t i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
1968
      {
1969
1
        const DTypeConstructor& cons = dt[i];
1970
        // make a sygus term
1971
2
        std::vector<Node> cchildren;
1972
1
        cchildren.push_back(cons.getConstructor());
1973
1
        for (size_t j = 0, nargs = cons.getNumArgs(); j < nargs; j++)
1974
        {
1975
          TypeNode argType = cons[j].getRangeType();
1976
          std::stringstream ss;
1977
          ss << argType;
1978
          Node bv = nm->mkBoundVar(ss.str(), argType);
1979
          cchildren.push_back(bv);
1980
          // if fresh type, store it for later processing
1981
          if (grammarTypes.insert(argType).second)
1982
          {
1983
            typesToPrint.push_back(argType);
1984
          }
1985
        }
1986
2
        Node consToPrint = nm->mkNode(kind::APPLY_CONSTRUCTOR, cchildren);
1987
        // now, print it using the conversion to builtin with external
1988
3
        types_list << theory::datatypes::utils::sygusToBuiltin(consToPrint,
1989
2
                                                               true);
1990
1
        types_list << ' ';
1991
      }
1992
1
      types_list << "))\n";
1993
1
    } while (!typesToPrint.empty());
1994
1995
1
    out << "\n(" << types_predecl.str() << ")\n(" << types_list.str() << ')';
1996
  }
1997
1
}
1998
1999
2
void Smt2Printer::toStreamCmdSynthFun(std::ostream& out,
2000
                                      Node f,
2001
                                      const std::vector<Node>& vars,
2002
                                      bool isInv,
2003
                                      TypeNode sygusType) const
2004
{
2005
4
  std::stringstream sym;
2006
2
  sym << f;
2007
  out << '(' << (isInv ? "synth-inv " : "synth-fun ")
2008
2
      << cvc5::quoteSymbol(sym.str()) << ' ';
2009
2
  out << '(';
2010
2
  if (!vars.empty())
2011
  {
2012
    // print variable list
2013
2
    std::vector<Node>::const_iterator i = vars.cbegin(), i_end = vars.cend();
2014
2
    out << '(' << *i << ' ' << i->getType() << ')';
2015
2
    ++i;
2016
2
    while (i != i_end)
2017
    {
2018
      out << " (" << *i << ' ' << i->getType() << ')';
2019
      ++i;
2020
    }
2021
  }
2022
2
  out << ')';
2023
  // if not invariant-to-synthesize, print return type
2024
2
  if (!isInv)
2025
  {
2026
2
    TypeNode ftn = f.getType();
2027
2
    TypeNode range = ftn.isFunction() ? ftn.getRangeType() : ftn;
2028
1
    out << ' ' << range;
2029
  }
2030
2
  out << '\n';
2031
  // print grammar, if any
2032
2
  if (!sygusType.isNull())
2033
  {
2034
1
    toStreamSygusGrammar(out, sygusType);
2035
  }
2036
2
  out << ')' << std::endl;
2037
2
}
2038
2039
1
void Smt2Printer::toStreamCmdDeclareVar(std::ostream& out,
2040
                                        Node var,
2041
                                        TypeNode type) const
2042
{
2043
1
  out << "(declare-var " << var << ' ' << type << ')' << std::endl;
2044
1
}
2045
2046
1
void Smt2Printer::toStreamCmdConstraint(std::ostream& out, Node n) const
2047
{
2048
1
  out << "(constraint " << n << ')' << std::endl;
2049
1
}
2050
2051
1
void Smt2Printer::toStreamCmdInvConstraint(
2052
    std::ostream& out, Node inv, Node pre, Node trans, Node post) const
2053
{
2054
2
  out << "(inv-constraint " << inv << ' ' << pre << ' ' << trans << ' ' << post
2055
1
      << ')' << std::endl;
2056
1
}
2057
2058
1
void Smt2Printer::toStreamCmdCheckSynth(std::ostream& out) const
2059
{
2060
1
  out << "(check-synth)" << std::endl;
2061
1
}
2062
2063
void Smt2Printer::toStreamCmdGetAbduct(std::ostream& out,
2064
                                       const std::string& name,
2065
                                       Node conj,
2066
                                       TypeNode sygusType) const
2067
{
2068
  out << "(get-abduct ";
2069
  out << name << ' ';
2070
  out << conj << ' ';
2071
2072
  // print grammar, if any
2073
  if (!sygusType.isNull())
2074
  {
2075
    toStreamSygusGrammar(out, sygusType);
2076
  }
2077
  out << ')' << std::endl;
2078
}
2079
2080
/*
2081
   --------------------------------------------------------------------------
2082
    End of Handling SyGuS commands
2083
   --------------------------------------------------------------------------
2084
*/
2085
2086
template <class T>
2087
static bool tryToStream(std::ostream& out, const Command* c)
2088
{
2089
  if(typeid(*c) == typeid(T)) {
2090
    toStream(out, dynamic_cast<const T*>(c));
2091
    return true;
2092
  }
2093
  return false;
2094
}
2095
2096
template <class T>
2097
static bool tryToStream(std::ostream& out, const Command* c, Variant v)
2098
{
2099
  if(typeid(*c) == typeid(T)) {
2100
    toStream(out, dynamic_cast<const T*>(c), v);
2101
    return true;
2102
  }
2103
  return false;
2104
}
2105
2106
266746
static void toStream(std::ostream& out, const CommandSuccess* s, Variant v)
2107
{
2108
266746
  if(Command::printsuccess::getPrintSuccess(out)) {
2109
18
    out << "success" << endl;
2110
  }
2111
266746
}
2112
2113
static void toStream(std::ostream& out, const CommandInterrupted* s, Variant v)
2114
{
2115
  out << "interrupted" << endl;
2116
}
2117
2118
static void toStream(std::ostream& out, const CommandUnsupported* s, Variant v)
2119
{
2120
#ifdef CVC5_COMPETITION_MODE
2121
  // if in competition mode, lie and say we're ok
2122
  // (we have nothing to lose by saying success, and everything to lose
2123
  // if we say "unsupported")
2124
  out << "success" << endl;
2125
#else  /* CVC5_COMPETITION_MODE */
2126
  out << "unsupported" << endl;
2127
#endif /* CVC5_COMPETITION_MODE */
2128
}
2129
2130
46
static void errorToStream(std::ostream& out, std::string message, Variant v) {
2131
  // escape all double-quotes
2132
46
  size_t pos = 0;
2133
50
  while((pos = message.find('"', pos)) != string::npos) {
2134
2
    message.replace(pos, 1, "\"\"");
2135
2
    pos += 2;
2136
  }
2137
46
  out << "(error \"" << message << "\")" << endl;
2138
46
}
2139
2140
31
static void toStream(std::ostream& out, const CommandFailure* s, Variant v) {
2141
31
  errorToStream(out, s->getMessage(), v);
2142
31
}
2143
2144
15
static void toStream(std::ostream& out, const CommandRecoverableFailure* s,
2145
                     Variant v) {
2146
15
  errorToStream(out, s->getMessage(), v);
2147
15
}
2148
2149
template <class T>
2150
266853
static bool tryToStream(std::ostream& out, const CommandStatus* s, Variant v)
2151
{
2152
266853
  if(typeid(*s) == typeid(T)) {
2153
266792
    toStream(out, dynamic_cast<const T*>(s), v);
2154
266792
    return true;
2155
  }
2156
61
  return false;
2157
}
2158
2159
}  // namespace smt2
2160
}  // namespace printer
2161
28395
}  // namespace cvc5