GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/printer/smt2/smt2_printer.cpp Lines: 600 1187 50.5 %
Date: 2021-09-22 Branches: 954 3050 31.3 %

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