GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/printer/smt2/smt2_printer.cpp Lines: 605 1193 50.7 %
Date: 2021-08-16 Branches: 980 3142 31.2 %

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
221427
static void toStreamRational(std::ostream& out,
67
                             const Rational& r,
68
                             bool decimal,
69
                             Variant v)
70
{
71
221427
  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
221427
  if (r.isIntegral())
76
  {
77
221302
    if (neg)
78
    {
79
89012
      out << "(- " << -r;
80
    }
81
    else
82
    {
83
132290
      out << r;
84
    }
85
221302
    if (decimal)
86
    {
87
16
      out << ".0";
88
    }
89
221302
    if (neg)
90
    {
91
89012
      out << ")";
92
    }
93
  }
94
  else
95
  {
96
125
    out << "(/ ";
97
125
    if (neg)
98
    {
99
68
      Rational abs_r = (-r);
100
34
      out << "(- " << abs_r.getNumerator();
101
34
      out << ") " << abs_r.getDenominator();
102
    }
103
    else
104
    {
105
91
      out << r.getNumerator();
106
91
      out << ' ' << r.getDenominator();
107
    }
108
125
    out << ')';
109
  }
110
221427
}
111
112
77549
void Smt2Printer::toStream(std::ostream& out,
113
                           TNode n,
114
                           int toDepth,
115
                           size_t dag) const
116
{
117
77549
  if(dag != 0) {
118
103676
    LetBinding lbind(dag + 1);
119
51852
    toStreamWithLetify(out, n, toDepth, &lbind);
120
  } else {
121
25711
    toStream(out, n, toDepth);
122
  }
123
77535
}
124
125
51838
void Smt2Printer::toStreamWithLetify(std::ostream& out,
126
                                     Node n,
127
                                     int toDepth,
128
                                     LetBinding* lbind) const
129
{
130
51838
  if (lbind == nullptr)
131
  {
132
    toStream(out, n, toDepth);
133
    return;
134
  }
135
103676
  std::stringstream cparen;
136
103676
  std::vector<Node> letList;
137
51838
  lbind->letify(n, letList);
138
51838
  if (!letList.empty())
139
  {
140
37967
    std::map<Node, uint32_t>::const_iterator it;
141
144544
    for (size_t i = 0, nlets = letList.size(); i < nlets; i++)
142
    {
143
213154
      Node nl = letList[i];
144
106577
      out << "(let ((";
145
106577
      uint32_t id = lbind->getId(nl);
146
106577
      out << "_let_" << id << " ";
147
213154
      Node nlc = lbind->convert(nl, "_let_", false);
148
106577
      toStream(out, nlc, toDepth, lbind);
149
106577
      out << ")) ";
150
106577
      cparen << ")";
151
    }
152
  }
153
103676
  Node nc = lbind->convert(n, "_let_");
154
  // print the body, passing the lbind object
155
51824
  toStream(out, nc, toDepth, lbind);
156
51824
  out << cparen.str();
157
51824
  lbind->popScope();
158
}
159
160
1840727
void Smt2Printer::toStream(std::ostream& out,
161
                           TNode n,
162
                           int toDepth,
163
                           LetBinding* lbind) const
164
{
165
  // null
166
1840727
  if(n.getKind() == kind::NULL_EXPR) {
167
    out << "null";
168
1130617
    return;
169
  }
170
171
1840727
  NodeManager* nm = NodeManager::currentNM();
172
  // constant
173
1840727
  if(n.getMetaKind() == kind::metakind::CONSTANT) {
174
279879
    switch(n.getKind()) {
175
10413
    case kind::TYPE_CONSTANT:
176
10413
      switch(n.getConst<TypeConstant>()) {
177
1884
      case BOOLEAN_TYPE: out << "Bool"; break;
178
532
      case REAL_TYPE: out << "Real"; break;
179
7383
      case INTEGER_TYPE: out << "Int"; break;
180
543
      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
10413
      break;
189
3357
    case kind::BITVECTOR_TYPE:
190
3357
      out << "(_ BitVec " << n.getConst<BitVectorSize>().d_size << ")";
191
3357
      break;
192
222
    case kind::FLOATINGPOINT_TYPE:
193
222
      out << "(_ FloatingPoint "
194
222
          << n.getConst<FloatingPointSize>().exponentWidth() << " "
195
222
          << n.getConst<FloatingPointSize>().significandWidth() << ")";
196
222
      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
39032
    case kind::CONST_BOOLEAN:
237
      // the default would print "1" or "0" for bool, that's not correct
238
      // for our purposes
239
39032
      out << (n.getConst<bool>() ? "true" : "false");
240
39032
      break;
241
    case kind::BUILTIN:
242
      out << smtKindString(n.getConst<Kind>(), d_variant);
243
      break;
244
221411
    case kind::CONST_RATIONAL: {
245
221411
      const Rational& r = n.getConst<Rational>();
246
221411
      toStreamRational(out, r, false, d_variant);
247
221411
      break;
248
    }
249
250
3077
    case kind::CONST_STRING: {
251
6154
      std::string s = n.getConst<String>().toString();
252
3077
      out << '"';
253
6613
      for(size_t i = 0; i < s.size(); ++i) {
254
3536
        char c = s[i];
255
3536
        if(c == '"') {
256
4
          out << "\"\"";
257
        } else {
258
3532
          out << c;
259
        }
260
      }
261
3077
      out << '"';
262
3077
      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
2092
    case kind::DATATYPE_TYPE:
299
    {
300
      const DType& dt = (NodeManager::currentNM()->getDTypeForIndex(
301
2092
          n.getConst<DatatypeIndexConstant>().getIndex()));
302
2092
      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
2086
        out << cvc5::quoteSymbol(dt.getName());
323
      }
324
2092
      break;
325
    }
326
327
1
    case kind::UNINTERPRETED_CONSTANT: {
328
1
      const UninterpretedConstant& uc = n.getConst<UninterpretedConstant>();
329
2
      std::stringstream ss;
330
1
      ss << "(as @" << uc << " " << n.getType() << ")";
331
1
      out << ss.str();
332
1
      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
279879
    return;
463
  }
464
465
1560848
  if(n.getKind() == kind::SORT_TYPE) {
466
12270
    string name;
467
6135
    if(n.getNumChildren() != 0) {
468
28
      out << '(';
469
    }
470
6135
    if(n.getAttribute(expr::VarNameAttr(), name)) {
471
6135
      out << cvc5::quoteSymbol(name);
472
    }
473
6135
    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
6135
    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
1554713
  Kind k = n.getKind();
486
2264823
  Node type_asc_arg;
487
2264823
  TypeNode force_nt;
488
1554713
  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
1554693
  else if (k == kind::CAST_TO_REAL)
494
  {
495
16
    force_nt = nm->realType();
496
16
    type_asc_arg = n[0];
497
  }
498
1554713
  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
1554677
  if (n.isVar())
539
  {
540
1685468
    string s;
541
842734
    if (n.getAttribute(expr::VarNameAttr(), s))
542
    {
543
837746
      out << cvc5::quoteSymbol(s);
544
    }
545
    else
546
    {
547
4988
      if (n.getKind() == kind::VARIABLE)
548
      {
549
        out << "var_";
550
      }
551
      else
552
      {
553
4988
        out << n.getKind() << '_';
554
      }
555
4988
      out << n.getId();
556
    }
557
842734
    return;
558
  }
559
560
711943
  bool stillNeedToPrintParams = true;
561
711943
  bool forceBinary = false; // force N-ary to binary when outputing children
562
  // operator
563
711943
  if (n.getNumChildren() != 0 && k != kind::CONSTRUCTOR_TYPE)
564
  {
565
710981
    out << '(';
566
  }
567
711943
  switch(k) {
568
    // builtin theory
569
893
    case kind::FUNCTION_TYPE:
570
893
      out << "->";
571
3703
      for (Node nc : n)
572
      {
573
2810
        out << " ";
574
2810
        toStream(out, nc, toDepth);
575
893
      }
576
893
      out << ")";
577
893
      return;
578
426235
    case kind::SEXPR: break;
579
580
    // uf theory
581
39745
    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
690
  // sets
691
12
  case kind::SINGLETON:
692
  {
693
12
    out << smtKindString(k, d_variant) << " ";
694
24
    TypeNode elemType = n.getType().getSetElementType();
695
12
    toStreamCastToType(
696
        out, n[0], toDepth < 0 ? toDepth : toDepth - 1, elemType);
697
12
    out << ")";
698
12
    return;
699
  }
700
  break;
701
  case kind::UNIVERSE_SET:out << "(as univset " << n.getType() << ")";break;
702
703
  // bags
704
4
  case kind::MK_BAG:
705
  {
706
    // print (bag (mkBag_op Real) 1 3) as (bag 1.0 3)
707
4
    out << smtKindString(k, d_variant) << " ";
708
8
    TypeNode elemType = n.getType().getBagElementType();
709
4
    toStreamCastToType(
710
        out, n[0], toDepth < 0 ? toDepth : toDepth - 1, elemType);
711
4
    out << " " << n[1] << ")";
712
4
    return;
713
  }
714
715
  // fp theory
716
2
  case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
717
  case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT:
718
  case kind::FLOATINGPOINT_TO_FP_REAL:
719
  case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
720
  case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
721
  case kind::FLOATINGPOINT_TO_FP_GENERIC:
722
  case kind::FLOATINGPOINT_TO_UBV:
723
  case kind::FLOATINGPOINT_TO_SBV:
724
2
    out << n.getOperator() << ' ';
725
2
    stillNeedToPrintParams = false;
726
2
    break;
727
728
5849
  case kind::APPLY_CONSTRUCTOR:
729
  {
730
5849
    const DType& dt = DType::datatypeOf(n.getOperator());
731
5849
    if (dt.isTuple())
732
    {
733
28
      stillNeedToPrintParams = false;
734
28
      out << "mkTuple" << ( dt[0].getNumArgs()==0 ? "" : " ");
735
    }
736
5849
    break;
737
  }
738
6
  case kind::TUPLE_PROJECT:
739
  {
740
12
    TupleProjectOp op = n.getOperator().getConst<TupleProjectOp>();
741
6
    if (op.getIndices().empty())
742
    {
743
      // e.g. (tuple_project tuple)
744
      out << "project " << n[0] << ")";
745
    }
746
    else
747
    {
748
      // e.g. ((_ tuple_project 2 4 4) tuple)
749
6
      out << "(_ tuple_project" << op << ") " << n[0] << ")";
750
    }
751
6
    return;
752
  }
753
12
  case kind::CONSTRUCTOR_TYPE:
754
  {
755
12
    out << n[n.getNumChildren()-1];
756
12
    return;
757
    break;
758
  }
759
  case kind::APPLY_SELECTOR:
760
  {
761
    Node op = n.getOperator();
762
    const DType& dt = DType::datatypeOf(op);
763
    if (dt.isTuple())
764
    {
765
      stillNeedToPrintParams = false;
766
      out << "(_ tupSel " << DType::indexOf(op) << ") ";
767
    }
768
  }
769
  break;
770
  case kind::APPLY_TESTER:
771
  {
772
    stillNeedToPrintParams = false;
773
    Node op = n.getOperator();
774
    size_t cindex = DType::indexOf(op);
775
    const DType& dt = DType::datatypeOf(op);
776
    out << "(_ is ";
777
    toStream(
778
        out, dt[cindex].getConstructor(), toDepth < 0 ? toDepth : toDepth - 1);
779
    out << ") ";
780
  }
781
  break;
782
  case kind::APPLY_UPDATER:
783
  {
784
    Node op = n.getOperator();
785
    size_t index = DType::indexOf(op);
786
    const DType& dt = DType::datatypeOf(op);
787
    size_t cindex = DType::cindexOf(op);
788
    out << "(_ update ";
789
    toStream(out,
790
             dt[cindex][index].getSelector(),
791
             toDepth < 0 ? toDepth : toDepth - 1);
792
    out << ") ";
793
  }
794
  break;
795
1152
  case kind::APPLY_SELECTOR_TOTAL:
796
1152
  case kind::PARAMETRIC_DATATYPE: break;
797
798
  // separation logic
799
104
  case kind::SEP_NIL:
800
104
    out << "(as sep.nil " << n.getType() << ")";
801
104
    break;
802
803
    // quantifiers
804
53
  case kind::FORALL:
805
  case kind::EXISTS:
806
  case kind::LAMBDA:
807
  case kind::WITNESS:
808
  {
809
53
    out << smtKindString(k, d_variant) << " ";
810
    // do not letify the bound variable list
811
53
    toStream(out, n[0], toDepth, nullptr);
812
53
    out << " ";
813
106
    std::stringstream annot;
814
53
    if (n.getNumChildren() == 3)
815
    {
816
2
      annot << " ";
817
4
      for (const Node& nc : n[2])
818
      {
819
2
        if (nc.getKind() == kind::INST_PATTERN)
820
        {
821
          out << "(! ";
822
          annot << ":pattern ";
823
          toStream(annot, nc, toDepth, nullptr);
824
          annot << ") ";
825
        }
826
2
        else if (nc.getKind() == kind::INST_NO_PATTERN)
827
        {
828
          out << "(! ";
829
          annot << ":no-pattern ";
830
          toStream(annot, nc, toDepth, nullptr);
831
          annot << ") ";
832
        }
833
      }
834
    }
835
    // Use a fresh let binder, since using existing let symbols may violate
836
    // scoping issues for let-bound variables, see explanation in let_binding.h.
837
53
    size_t dag = lbind == nullptr ? 0 : lbind->getThreshold()-1;
838
53
    toStream(out, n[1], toDepth - 1, dag);
839
53
    out << annot.str() << ")";
840
53
    return;
841
    break;
842
  }
843
853
  case kind::BOUND_VAR_LIST:
844
  {
845
    // the left parenthesis is already printed (before the switch)
846
2758
    for (TNode::iterator i = n.begin(), iend = n.end(); i != iend;)
847
    {
848
1905
      out << '(';
849
1905
      toStream(out, *i, toDepth < 0 ? toDepth : toDepth - 1);
850
1905
      out << ' ';
851
1905
      out << (*i).getType();
852
1905
      out << ')';
853
1905
      if (++i != iend)
854
      {
855
1052
        out << ' ';
856
      }
857
    }
858
853
    out << ')';
859
853
    return;
860
  }
861
  case kind::INST_PATTERN:
862
  case kind::INST_NO_PATTERN:
863
  case kind::INST_PATTERN_LIST: break;
864
236422
  default:
865
    // by default, print the kind using the smtKindString utility
866
236422
    out << smtKindString(k, d_variant) << " ";
867
236422
    break;
868
  }
869
710110
  if( n.getMetaKind() == kind::metakind::PARAMETERIZED &&
870
      stillNeedToPrintParams ) {
871
46690
    if(toDepth != 0) {
872
93380
      toStream(
873
93380
          out, n.getOperator(), toDepth < 0 ? toDepth : toDepth - 1, lbind);
874
    } else {
875
      out << "(...)";
876
    }
877
46690
    if(n.getNumChildren() > 0) {
878
46363
      out << ' ';
879
    }
880
  }
881
1420220
  stringstream parens;
882
883
2315151
  for(size_t i = 0, c = 1; i < n.getNumChildren(); ) {
884
1605041
    if(toDepth != 0) {
885
1605041
      toStream(out, n[i], toDepth < 0 ? toDepth : toDepth - c, lbind);
886
    } else {
887
      out << "(...)";
888
    }
889
1605041
    if(++i < n.getNumChildren()) {
890
895881
      if(forceBinary && i < n.getNumChildren() - 1) {
891
        // not going to work properly for parameterized kinds!
892
        Assert(n.getMetaKind() != kind::metakind::PARAMETERIZED);
893
        out << " (" << smtKindString(n.getKind(), d_variant) << ' ';
894
        parens << ')';
895
        ++c;
896
      } else {
897
895881
        out << ' ';
898
      }
899
    }
900
  }
901
710110
  if (n.getNumChildren() != 0)
902
  {
903
709160
    out << parens.str() << ')';
904
  }
905
}
906
907
40
void Smt2Printer::toStreamCastToType(std::ostream& out,
908
                                     TNode n,
909
                                     int toDepth,
910
                                     TypeNode tn) const
911
{
912
80
  Node nasc;
913
40
  if (n.getType().isInteger() && !tn.isInteger())
914
  {
915
2
    Assert(tn.isReal());
916
    // probably due to subtyping integers and reals, cast it
917
2
    nasc = NodeManager::currentNM()->mkNode(kind::CAST_TO_REAL, n);
918
  }
919
  else
920
  {
921
38
    nasc = n;
922
  }
923
40
  toStream(out, nasc, toDepth);
924
40
}
925
926
237063
std::string Smt2Printer::smtKindString(Kind k, Variant v)
927
{
928
237063
  switch(k) {
929
    // builtin theory
930
49138
  case kind::EQUAL: return "=";
931
4
  case kind::DISTINCT: return "distinct";
932
  case kind::SEXPR: break;
933
934
    // bool theory
935
26652
  case kind::NOT: return "not";
936
254
  case kind::AND: return "and";
937
7
  case kind::IMPLIES: return "=>";
938
53
  case kind::OR: return "or";
939
20
  case kind::XOR: return "xor";
940
4
  case kind::ITE: return "ite";
941
942
    // uf theory
943
  case kind::APPLY_UF: break;
944
945
15
  case kind::LAMBDA: return "lambda";
946
  case kind::MATCH: return "match";
947
2
  case kind::WITNESS: return "witness";
948
949
  // arith theory
950
46760
  case kind::PLUS: return "+";
951
41386
  case kind::MULT:
952
41386
  case kind::NONLINEAR_MULT: return "*";
953
  case kind::IAND: return "iand";
954
10
  case kind::POW2: return "POW2";
955
31
  case kind::EXPONENTIAL: return "exp";
956
264
  case kind::SINE: return "sin";
957
  case kind::COSINE: return "cos";
958
  case kind::TANGENT: return "tan";
959
  case kind::COSECANT: return "csc";
960
  case kind::SECANT: return "sec";
961
  case kind::COTANGENT: return "cot";
962
  case kind::ARCSINE: return "arcsin";
963
  case kind::ARCCOSINE: return "arccos";
964
  case kind::ARCTANGENT: return "arctan";
965
  case kind::ARCCOSECANT: return "arccsc";
966
  case kind::ARCSECANT: return "arcsec";
967
  case kind::ARCCOTANGENT: return "arccot";
968
300
  case kind::PI: return "real.pi";
969
  case kind::SQRT: return "sqrt";
970
6
  case kind::MINUS: return "-";
971
2
  case kind::UMINUS: return "-";
972
21258
  case kind::LT: return "<";
973
82
  case kind::LEQ: return "<=";
974
2393
  case kind::GT: return ">";
975
34597
  case kind::GEQ: return ">=";
976
5
  case kind::DIVISION:
977
5
  case kind::DIVISION_TOTAL: return "/";
978
3
  case kind::INTS_DIVISION_TOTAL:
979
3
  case kind::INTS_DIVISION: return "div";
980
1
  case kind::INTS_MODULUS_TOTAL:
981
1
  case kind::INTS_MODULUS: return "mod";
982
  case kind::ABS: return "abs";
983
  case kind::IS_INTEGER: return "is_int";
984
  case kind::TO_INTEGER: return "to_int";
985
  case kind::TO_REAL: return "to_real";
986
  case kind::POW: return "^";
987
988
    // arrays theory
989
285
  case kind::SELECT: return "select";
990
  case kind::STORE: return "store";
991
217
  case kind::ARRAY_TYPE: return "Array";
992
  case kind::PARTIAL_SELECT_0: return "partial_select_0";
993
  case kind::PARTIAL_SELECT_1: return "partial_select_1";
994
  case kind::EQ_RANGE:
995
    return "eqrange";
996
997
    // bv theory
998
  case kind::BITVECTOR_CONCAT: return "concat";
999
95
  case kind::BITVECTOR_AND: return "bvand";
1000
93
  case kind::BITVECTOR_OR: return "bvor";
1001
  case kind::BITVECTOR_XOR: return "bvxor";
1002
123
  case kind::BITVECTOR_NOT: return "bvnot";
1003
  case kind::BITVECTOR_NAND: return "bvnand";
1004
  case kind::BITVECTOR_NOR: return "bvnor";
1005
  case kind::BITVECTOR_XNOR: return "bvxnor";
1006
  case kind::BITVECTOR_COMP: return "bvcomp";
1007
187
  case kind::BITVECTOR_MULT: return "bvmul";
1008
197
  case kind::BITVECTOR_ADD: return "bvadd";
1009
  case kind::BITVECTOR_SUB: return "bvsub";
1010
100
  case kind::BITVECTOR_NEG: return "bvneg";
1011
  case kind::BITVECTOR_UDIV: return "bvudiv";
1012
  case kind::BITVECTOR_UREM: return "bvurem";
1013
  case kind::BITVECTOR_SDIV: return "bvsdiv";
1014
  case kind::BITVECTOR_SREM: return "bvsrem";
1015
  case kind::BITVECTOR_SMOD: return "bvsmod";
1016
310
  case kind::BITVECTOR_SHL: return "bvshl";
1017
269
  case kind::BITVECTOR_LSHR: return "bvlshr";
1018
  case kind::BITVECTOR_ASHR: return "bvashr";
1019
2
  case kind::BITVECTOR_ULT: return "bvult";
1020
  case kind::BITVECTOR_ULE: return "bvule";
1021
  case kind::BITVECTOR_UGT: return "bvugt";
1022
  case kind::BITVECTOR_UGE: return "bvuge";
1023
  case kind::BITVECTOR_SLT: return "bvslt";
1024
  case kind::BITVECTOR_SLE: return "bvsle";
1025
  case kind::BITVECTOR_SGT: return "bvsgt";
1026
  case kind::BITVECTOR_SGE: return "bvsge";
1027
  case kind::BITVECTOR_TO_NAT: return "bv2nat";
1028
  case kind::BITVECTOR_REDOR: return "bvredor";
1029
  case kind::BITVECTOR_REDAND: return "bvredand";
1030
1031
  case kind::BITVECTOR_EXTRACT: return "extract";
1032
  case kind::BITVECTOR_REPEAT: return "repeat";
1033
  case kind::BITVECTOR_ZERO_EXTEND: return "zero_extend";
1034
  case kind::BITVECTOR_SIGN_EXTEND: return "sign_extend";
1035
  case kind::BITVECTOR_ROTATE_LEFT: return "rotate_left";
1036
  case kind::BITVECTOR_ROTATE_RIGHT: return "rotate_right";
1037
  case kind::INT_TO_BITVECTOR: return "int2bv";
1038
  case kind::BITVECTOR_BB_TERM: return "bbT";
1039
1040
  // datatypes theory
1041
  case kind::APPLY_TESTER: return "is";
1042
  case kind::APPLY_UPDATER: return "update";
1043
1044
  // set theory
1045
  case kind::UNION: return "union";
1046
  case kind::INTERSECTION: return "intersection";
1047
  case kind::SETMINUS: return "setminus";
1048
  case kind::SUBSET: return "subset";
1049
  case kind::MEMBER: return "member";
1050
69
  case kind::SET_TYPE: return "Set";
1051
12
  case kind::SINGLETON: return "singleton";
1052
  case kind::INSERT: return "insert";
1053
  case kind::COMPLEMENT: return "complement";
1054
2
  case kind::CARD: return "card";
1055
  case kind::COMPREHENSION: return "comprehension";
1056
  case kind::CHOOSE: return "choose";
1057
  case kind::IS_SINGLETON: return "is_singleton";
1058
  case kind::JOIN: return "join";
1059
  case kind::PRODUCT: return "product";
1060
  case kind::TRANSPOSE: return "transpose";
1061
  case kind::TCLOSURE: return "tclosure";
1062
  case kind::IDEN: return "iden";
1063
  case kind::JOIN_IMAGE: return "join_image";
1064
1065
  // bag theory
1066
2
  case kind::BAG_TYPE: return "Bag";
1067
  case kind::UNION_MAX: return "union_max";
1068
  case kind::UNION_DISJOINT: return "union_disjoint";
1069
  case kind::INTERSECTION_MIN: return "intersection_min";
1070
  case kind::DIFFERENCE_SUBTRACT: return "difference_subtract";
1071
  case kind::DIFFERENCE_REMOVE: return "difference_remove";
1072
  case kind::SUBBAG: return "subbag";
1073
26
  case kind::BAG_COUNT: return "bag.count";
1074
6
  case kind::DUPLICATE_REMOVAL: return "duplicate_removal";
1075
4
  case kind::MK_BAG: return "bag";
1076
  case kind::BAG_CARD: return "bag.card";
1077
  case kind::BAG_CHOOSE: return "bag.choose";
1078
  case kind::BAG_IS_SINGLETON: return "bag.is_singleton";
1079
  case kind::BAG_FROM_SET: return "bag.from_set";
1080
  case kind::BAG_TO_SET: return "bag.to_set";
1081
1082
    // fp theory
1083
  case kind::FLOATINGPOINT_FP: return "fp";
1084
  case kind::FLOATINGPOINT_EQ: return "fp.eq";
1085
1
  case kind::FLOATINGPOINT_ABS: return "fp.abs";
1086
2
  case kind::FLOATINGPOINT_NEG: return "fp.neg";
1087
6
  case kind::FLOATINGPOINT_ADD: return "fp.add";
1088
13
  case kind::FLOATINGPOINT_SUB: return "fp.sub";
1089
12
  case kind::FLOATINGPOINT_MULT: return "fp.mul";
1090
21
  case kind::FLOATINGPOINT_DIV: return "fp.div";
1091
  case kind::FLOATINGPOINT_FMA: return "fp.fma";
1092
1
  case kind::FLOATINGPOINT_SQRT: return "fp.sqrt";
1093
17
  case kind::FLOATINGPOINT_REM: return "fp.rem";
1094
  case kind::FLOATINGPOINT_RTI: return "fp.roundToIntegral";
1095
  case kind::FLOATINGPOINT_MIN: return "fp.min";
1096
  case kind::FLOATINGPOINT_MAX: return "fp.max";
1097
  case kind::FLOATINGPOINT_MIN_TOTAL: return "fp.min_total";
1098
  case kind::FLOATINGPOINT_MAX_TOTAL: return "fp.max_total";
1099
1100
  case kind::FLOATINGPOINT_LEQ: return "fp.leq";
1101
  case kind::FLOATINGPOINT_LT: return "fp.lt";
1102
  case kind::FLOATINGPOINT_GEQ: return "fp.geq";
1103
  case kind::FLOATINGPOINT_GT: return "fp.gt";
1104
1105
1
  case kind::FLOATINGPOINT_ISN: return "fp.isNormal";
1106
1
  case kind::FLOATINGPOINT_ISSN: return "fp.isSubnormal";
1107
1
  case kind::FLOATINGPOINT_ISZ: return "fp.isZero";
1108
  case kind::FLOATINGPOINT_ISINF: return "fp.isInfinite";
1109
1
  case kind::FLOATINGPOINT_ISNAN: return "fp.isNaN";
1110
1
  case kind::FLOATINGPOINT_ISNEG: return "fp.isNegative";
1111
1
  case kind::FLOATINGPOINT_ISPOS: return "fp.isPositive";
1112
1113
  case kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR: return "to_fp";
1114
  case kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT: return "to_fp";
1115
  case kind::FLOATINGPOINT_TO_FP_REAL: return "to_fp";
1116
  case kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR: return "to_fp";
1117
  case kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR: return "to_fp_unsigned";
1118
  case kind::FLOATINGPOINT_TO_FP_GENERIC: return "to_fp_unsigned";
1119
  case kind::FLOATINGPOINT_TO_UBV: return "fp.to_ubv";
1120
  case kind::FLOATINGPOINT_TO_UBV_TOTAL: return "fp.to_ubv_total";
1121
  case kind::FLOATINGPOINT_TO_SBV: return "fp.to_sbv";
1122
  case kind::FLOATINGPOINT_TO_SBV_TOTAL: return "fp.to_sbv_total";
1123
  case kind::FLOATINGPOINT_TO_REAL: return "fp.to_real";
1124
  case kind::FLOATINGPOINT_TO_REAL_TOTAL: return "fp.to_real_total";
1125
1126
  case kind::FLOATINGPOINT_COMPONENT_NAN: return "NAN";
1127
  case kind::FLOATINGPOINT_COMPONENT_INF: return "INF";
1128
  case kind::FLOATINGPOINT_COMPONENT_ZERO: return "ZERO";
1129
  case kind::FLOATINGPOINT_COMPONENT_SIGN: return "SIGN";
1130
  case kind::FLOATINGPOINT_COMPONENT_EXPONENT: return "EXPONENT";
1131
  case kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND: return "SIGNIFICAND";
1132
  case kind::ROUNDINGMODE_BITBLAST:
1133
    return "RMBITBLAST";
1134
1135
  //string theory
1136
480
  case kind::STRING_CONCAT: return "str.++";
1137
7270
  case kind::STRING_LENGTH: return "str.len";
1138
419
  case kind::STRING_SUBSTR: return "str.substr" ;
1139
  case kind::STRING_UPDATE: return "str.update";
1140
128
  case kind::STRING_CONTAINS: return "str.contains";
1141
16
  case kind::STRING_CHARAT: return "str.at" ;
1142
269
  case kind::STRING_INDEXOF: return "str.indexof";
1143
14
  case kind::STRING_INDEXOF_RE: return "str.indexof_re";
1144
1058
  case kind::STRING_REPLACE: return "str.replace";
1145
  case kind::STRING_REPLACE_ALL: return "str.replace_all";
1146
18
  case kind::STRING_REPLACE_RE: return "str.replace_re";
1147
12
  case kind::STRING_REPLACE_RE_ALL: return "str.replace_re_all";
1148
  case kind::STRING_TOLOWER: return "str.tolower";
1149
  case kind::STRING_TOUPPER: return "str.toupper";
1150
  case kind::STRING_REV: return "str.rev";
1151
4
  case kind::STRING_PREFIX: return "str.prefixof" ;
1152
4
  case kind::STRING_SUFFIX: return "str.suffixof" ;
1153
  case kind::STRING_LEQ: return "str.<=";
1154
  case kind::STRING_LT: return "str.<";
1155
2
  case kind::STRING_FROM_CODE: return "str.from_code";
1156
802
  case kind::STRING_TO_CODE: return "str.to_code";
1157
25
  case kind::STRING_ITOS: return "str.from_int";
1158
  case kind::STRING_STOI: return "str.to_int";
1159
6
  case kind::STRING_IN_REGEXP: return "str.in_re";
1160
248
  case kind::STRING_TO_REGEXP: return "str.to_re";
1161
  case kind::REGEXP_EMPTY: return "re.none";
1162
219
  case kind::REGEXP_SIGMA: return "re.allchar";
1163
144
  case kind::REGEXP_CONCAT: return "re.++";
1164
17
  case kind::REGEXP_UNION: return "re.union";
1165
4
  case kind::REGEXP_INTER: return "re.inter";
1166
118
  case kind::REGEXP_STAR: return "re.*";
1167
  case kind::REGEXP_PLUS: return "re.+";
1168
  case kind::REGEXP_OPT: return "re.opt";
1169
  case kind::REGEXP_RANGE: return "re.range";
1170
  case kind::REGEXP_REPEAT: return "re.^";
1171
  case kind::REGEXP_LOOP: return "re.loop";
1172
4
  case kind::REGEXP_COMPLEMENT: return "re.comp";
1173
  case kind::REGEXP_DIFF: return "re.diff";
1174
13
  case kind::SEQUENCE_TYPE: return "Seq";
1175
2
  case kind::SEQ_UNIT: return "seq.unit";
1176
29
  case kind::SEQ_NTH: return "seq.nth";
1177
1178
  //sep theory
1179
  case kind::SEP_STAR: return "sep";
1180
  case kind::SEP_PTO: return "pto";
1181
1
  case kind::SEP_WAND: return "wand";
1182
2
  case kind::SEP_EMP: return "emp";
1183
1184
  // quantifiers
1185
34
  case kind::FORALL: return "forall";
1186
2
  case kind::EXISTS: return "exists";
1187
1188
374
  default:
1189
    ; /* fall through */
1190
  }
1191
1192
  // fall back on however the kind prints itself; this probably
1193
  // won't be SMT-LIB v2 compliant, but it will be clear from the
1194
  // output that support for the kind needs to be added here.
1195
  // no SMT way to print these
1196
374
  return kind::kindToString(k);
1197
}
1198
1199
42
void Smt2Printer::toStreamType(std::ostream& out, TypeNode tn) const
1200
{
1201
  // we currently must call TypeNode::toStream here.
1202
42
  tn.toStream(out, language::output::LANG_SMTLIB_V2_6);
1203
42
}
1204
1205
template <class T>
1206
static bool tryToStream(std::ostream& out, const Command* c);
1207
template <class T>
1208
static bool tryToStream(std::ostream& out, const Command* c, Variant v);
1209
1210
2
static std::string quoteSymbol(TNode n) {
1211
4
  std::stringstream ss;
1212
2
  ss << n;
1213
4
  return cvc5::quoteSymbol(ss.str());
1214
}
1215
1216
template <class T>
1217
static bool tryToStream(std::ostream& out, const CommandStatus* s, Variant v);
1218
1219
264777
void Smt2Printer::toStream(std::ostream& out, const CommandStatus* s) const
1220
{
1221
529603
  if (tryToStream<CommandSuccess>(out, s, d_variant) ||
1222
64
      tryToStream<CommandFailure>(out, s, d_variant) ||
1223
15
      tryToStream<CommandRecoverableFailure>(out, s, d_variant) ||
1224
264777
      tryToStream<CommandUnsupported>(out, s, d_variant) ||
1225
      tryToStream<CommandInterrupted>(out, s, d_variant)) {
1226
264777
    return;
1227
  }
1228
1229
  out << "ERROR: don't know how to print a CommandStatus of class: "
1230
      << typeid(*s).name() << endl;
1231
1232
}/* Smt2Printer::toStream(CommandStatus*) */
1233
1234
12
void Smt2Printer::toStream(std::ostream& out, const UnsatCore& core) const
1235
{
1236
12
  out << "(" << std::endl;
1237
12
  if (core.useNames())
1238
  {
1239
    // use the names
1240
9
    const std::vector<std::string>& cnames = core.getCoreNames();
1241
28
    for (const std::string& cn : cnames)
1242
    {
1243
19
      out << cvc5::quoteSymbol(cn) << std::endl;
1244
    }
1245
  }
1246
  else
1247
  {
1248
    // otherwise, use the formulas
1249
6
    for (UnsatCore::const_iterator i = core.begin(); i != core.end(); ++i)
1250
    {
1251
3
      out << *i << endl;
1252
    }
1253
  }
1254
12
  out << ")" << endl;
1255
12
}/* Smt2Printer::toStream(UnsatCore, map<Expr, string>) */
1256
1257
21
void Smt2Printer::toStream(std::ostream& out, const smt::Model& m) const
1258
{
1259
21
  const theory::TheoryModel* tm = m.getTheoryModel();
1260
  //print the model comments
1261
42
  std::stringstream c;
1262
21
  tm->getComments(c);
1263
42
  std::string ln;
1264
21
  while( std::getline( c, ln ) ){
1265
    out << "; " << ln << std::endl;
1266
  }
1267
  //print the model
1268
21
  out << "(" << endl;
1269
  // don't need to print approximations since they are built into choice
1270
  // functions in the values of variables.
1271
21
  this->Printer::toStream(out, m);
1272
21
  out << ")" << endl;
1273
  //print the heap model, if it exists
1274
42
  Node h, neq;
1275
21
  if (tm->getHeapModel(h, neq))
1276
  {
1277
    // description of the heap+what nil is equal to fully describes model
1278
    out << "(heap" << endl;
1279
    out << h << endl;
1280
    out << neq << endl;
1281
    out << ")" << std::endl;
1282
  }
1283
21
}
1284
1285
4
void Smt2Printer::toStreamModelSort(std::ostream& out,
1286
                                    const smt::Model& m,
1287
                                    TypeNode tn) const
1288
{
1289
4
  if (!tn.isSort())
1290
  {
1291
    out << "ERROR: don't know how to print non uninterpreted sort in model: "
1292
        << tn << std::endl;
1293
    return;
1294
  }
1295
4
  const theory::TheoryModel* tm = m.getTheoryModel();
1296
8
  std::vector<Node> elements = tm->getDomainElements(tn);
1297
4
  if (options::modelUninterpPrint() == options::ModelUninterpPrintMode::DtEnum)
1298
  {
1299
    out << "(declare-datatypes ((" << tn << " 0)) (";
1300
    for (const Node& type_ref : elements)
1301
    {
1302
      out << "(" << type_ref << ")";
1303
    }
1304
    out << ")))" << endl;
1305
    return;
1306
  }
1307
  // print the cardinality
1308
4
  out << "; cardinality of " << tn << " is " << elements.size() << endl;
1309
8
  if (options::modelUninterpPrint()
1310
4
      == options::ModelUninterpPrintMode::DeclSortAndFun)
1311
  {
1312
    toStreamCmdDeclareType(out, tn);
1313
  }
1314
  // print the representatives
1315
8
  for (const Node& trn : elements)
1316
  {
1317
4
    if (trn.isVar())
1318
    {
1319
8
      if (options::modelUninterpPrint()
1320
              == options::ModelUninterpPrintMode::DeclSortAndFun
1321
4
          || options::modelUninterpPrint()
1322
                 == options::ModelUninterpPrintMode::DeclFun)
1323
      {
1324
4
        out << "(declare-fun " << quoteSymbol(trn) << " () " << tn << ")"
1325
2
            << endl;
1326
      }
1327
    }
1328
    else
1329
    {
1330
      out << "; rep: " << trn << endl;
1331
    }
1332
  }
1333
}
1334
1335
24
void Smt2Printer::toStreamModelTerm(std::ostream& out,
1336
                                    const smt::Model& m,
1337
                                    Node n) const
1338
{
1339
24
  const theory::TheoryModel* tm = m.getTheoryModel();
1340
  // We get the value from the theory model directly, which notice
1341
  // does not have to go through the standard SmtEngine::getValue interface.
1342
48
  Node val = tm->getValue(n);
1343
24
  if (val.getKind() == kind::LAMBDA)
1344
  {
1345
2
    TypeNode rangeType = n.getType().getRangeType();
1346
1
    out << "(define-fun " << n << " " << val[0] << " " << rangeType << " ";
1347
    // call toStream and force its type to be proper
1348
1
    toStreamCastToType(out, val[1], -1, rangeType);
1349
1
    out << ")" << endl;
1350
  }
1351
  else
1352
  {
1353
46
    if (options::modelUninterpPrint() == options::ModelUninterpPrintMode::DtEnum
1354
23
        && val.getKind() == kind::STORE)
1355
    {
1356
      TypeNode tn = val[1].getType();
1357
      const std::vector<Node>* type_refs =
1358
          tm->getRepSet()->getTypeRepsOrNull(tn);
1359
      if (tn.isSort() && type_refs != nullptr)
1360
      {
1361
        Cardinality indexCard(type_refs->size());
1362
        val = theory::arrays::TheoryArraysRewriter::normalizeConstant(
1363
            val, indexCard);
1364
      }
1365
    }
1366
23
    out << "(define-fun " << n << " () " << n.getType() << " ";
1367
    // call toStream and force its type to be proper
1368
23
    toStreamCastToType(out, val, -1, n.getType());
1369
23
    out << ")" << endl;
1370
  }
1371
24
}
1372
1373
7
void Smt2Printer::toStreamCmdAssert(std::ostream& out, Node n) const
1374
{
1375
7
  out << "(assert " << n << ')' << std::endl;
1376
7
}
1377
1378
void Smt2Printer::toStreamCmdPush(std::ostream& out) const
1379
{
1380
  out << "(push 1)" << std::endl;
1381
}
1382
1383
void Smt2Printer::toStreamCmdPop(std::ostream& out) const
1384
{
1385
  out << "(pop 1)" << std::endl;
1386
}
1387
1388
2
void Smt2Printer::toStreamCmdCheckSat(std::ostream& out, Node n) const
1389
{
1390
2
  if (!n.isNull())
1391
  {
1392
    toStreamCmdPush(out);
1393
    out << std::endl;
1394
    toStreamCmdAssert(out, n);
1395
    out << std::endl;
1396
    toStreamCmdCheckSat(out);
1397
    out << std::endl;
1398
    toStreamCmdPop(out);
1399
  }
1400
  else
1401
  {
1402
2
    out << "(check-sat)";
1403
  }
1404
2
  out << std::endl;
1405
2
}
1406
1407
void Smt2Printer::toStreamCmdCheckSatAssuming(
1408
    std::ostream& out, const std::vector<Node>& nodes) const
1409
{
1410
  out << "(check-sat-assuming ( ";
1411
  copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, " "));
1412
  out << "))" << std::endl;
1413
}
1414
1415
void Smt2Printer::toStreamCmdQuery(std::ostream& out, Node n) const
1416
{
1417
  if (!n.isNull())
1418
  {
1419
    toStreamCmdCheckSatAssuming(out, {n});
1420
  }
1421
  else
1422
  {
1423
    toStreamCmdCheckSat(out);
1424
  }
1425
}
1426
1427
void Smt2Printer::toStreamCmdReset(std::ostream& out) const
1428
{
1429
  out << "(reset)" << std::endl;
1430
}
1431
1432
void Smt2Printer::toStreamCmdResetAssertions(std::ostream& out) const
1433
{
1434
  out << "(reset-assertions)" << std::endl;
1435
}
1436
1437
void Smt2Printer::toStreamCmdQuit(std::ostream& out) const
1438
{
1439
  out << "(exit)" << std::endl;
1440
}
1441
1442
void Smt2Printer::toStreamCmdCommandSequence(
1443
    std::ostream& out, const std::vector<Command*>& sequence) const
1444
{
1445
  for (Command* i : sequence)
1446
  {
1447
    out << *i;
1448
  }
1449
}
1450
1451
void Smt2Printer::toStreamCmdDeclarationSequence(
1452
    std::ostream& out, const std::vector<Command*>& sequence) const
1453
{
1454
  toStreamCmdCommandSequence(out, sequence);
1455
}
1456
1457
10
void Smt2Printer::toStreamCmdDeclareFunction(std::ostream& out,
1458
                                             const std::string& id,
1459
                                             TypeNode type) const
1460
{
1461
10
  out << "(declare-fun " << cvc5::quoteSymbol(id) << " (";
1462
10
  if (type.isFunction())
1463
  {
1464
    const vector<TypeNode> argTypes = type.getArgTypes();
1465
    if (argTypes.size() > 0)
1466
    {
1467
      copy(argTypes.begin(),
1468
           argTypes.end() - 1,
1469
           ostream_iterator<TypeNode>(out, " "));
1470
      out << argTypes.back();
1471
    }
1472
    type = type.getRangeType();
1473
  }
1474
1475
10
  out << ") " << type << ')' << std::endl;
1476
10
}
1477
1478
7
void Smt2Printer::toStreamCmdDefineFunction(std::ostream& out,
1479
                                            const std::string& id,
1480
                                            const std::vector<Node>& formals,
1481
                                            TypeNode range,
1482
                                            Node formula) const
1483
{
1484
7
  out << "(define-fun " << id << " (";
1485
7
  if (!formals.empty())
1486
  {
1487
6
    vector<Node>::const_iterator i = formals.cbegin();
1488
    for (;;)
1489
    {
1490
12
      out << "(" << (*i) << " " << (*i).getType() << ")";
1491
9
      ++i;
1492
9
      if (i != formals.cend())
1493
      {
1494
3
        out << " ";
1495
      }
1496
      else
1497
      {
1498
6
        break;
1499
      }
1500
    }
1501
  }
1502
7
  out << ") " << range << ' ' << formula << ')' << std::endl;
1503
7
}
1504
1505
void Smt2Printer::toStreamCmdDefineFunctionRec(
1506
    std::ostream& out,
1507
    const std::vector<Node>& funcs,
1508
    const std::vector<std::vector<Node>>& formals,
1509
    const std::vector<Node>& formulas) const
1510
{
1511
  out << "(define-fun";
1512
  if (funcs.size() > 1)
1513
  {
1514
    out << "s";
1515
  }
1516
  out << "-rec ";
1517
  if (funcs.size() > 1)
1518
  {
1519
    out << "(";
1520
  }
1521
  for (unsigned i = 0, size = funcs.size(); i < size; i++)
1522
  {
1523
    if (funcs.size() > 1)
1524
    {
1525
      if (i > 0)
1526
      {
1527
        out << " ";
1528
      }
1529
      out << "(";
1530
    }
1531
    out << funcs[i] << " (";
1532
    // print its type signature
1533
    vector<Node>::const_iterator itf = formals[i].cbegin();
1534
    while (itf != formals[i].cend())
1535
    {
1536
      out << "(" << (*itf) << " " << (*itf).getType() << ")";
1537
      ++itf;
1538
      if (itf != formals[i].cend())
1539
      {
1540
        out << " ";
1541
      }
1542
    }
1543
    TypeNode type = funcs[i].getType();
1544
    if (type.isFunction())
1545
    {
1546
      type = type.getRangeType();
1547
    }
1548
    out << ") " << type;
1549
    if (funcs.size() > 1)
1550
    {
1551
      out << ")";
1552
    }
1553
  }
1554
  if (funcs.size() > 1)
1555
  {
1556
    out << ") (";
1557
  }
1558
  else
1559
  {
1560
    out << " ";
1561
  }
1562
  for (unsigned i = 0, size = formulas.size(); i < size; i++)
1563
  {
1564
    if (i > 0)
1565
    {
1566
      out << " ";
1567
    }
1568
    out << formulas[i];
1569
  }
1570
  if (funcs.size() > 1)
1571
  {
1572
    out << ")";
1573
  }
1574
  out << ")" << std::endl;
1575
}
1576
1577
void Smt2Printer::toStreamCmdDeclareType(std::ostream& out,
1578
                                         TypeNode type) const
1579
{
1580
  Assert(type.isSort() || type.isSortConstructor());
1581
  std::stringstream id;
1582
  id << type;
1583
  size_t arity = type.isSortConstructor() ? type.getSortConstructorArity() : 0;
1584
  out << "(declare-sort " << cvc5::quoteSymbol(id.str()) << " " << arity << ")"
1585
      << std::endl;
1586
}
1587
1588
void Smt2Printer::toStreamCmdDefineType(std::ostream& out,
1589
                                        const std::string& id,
1590
                                        const std::vector<TypeNode>& params,
1591
                                        TypeNode t) const
1592
{
1593
  out << "(define-sort " << cvc5::quoteSymbol(id) << " (";
1594
  if (params.size() > 0)
1595
  {
1596
    copy(
1597
        params.begin(), params.end() - 1, ostream_iterator<TypeNode>(out, " "));
1598
    out << params.back();
1599
  }
1600
  out << ") " << t << ")" << std::endl;
1601
}
1602
1603
void Smt2Printer::toStreamCmdSimplify(std::ostream& out, Node n) const
1604
{
1605
  out << "(simplify " << n << ')' << std::endl;
1606
}
1607
1608
void Smt2Printer::toStreamCmdGetValue(std::ostream& out,
1609
                                      const std::vector<Node>& nodes) const
1610
{
1611
  out << "(get-value ( ";
1612
  copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, " "));
1613
  out << "))" << std::endl;
1614
}
1615
1616
void Smt2Printer::toStreamCmdGetModel(std::ostream& out) const
1617
{
1618
  out << "(get-model)" << std::endl;
1619
}
1620
1621
void Smt2Printer::toStreamCmdGetAssignment(std::ostream& out) const
1622
{
1623
  out << "(get-assignment)" << std::endl;
1624
}
1625
1626
void Smt2Printer::toStreamCmdGetAssertions(std::ostream& out) const
1627
{
1628
  out << "(get-assertions)" << std::endl;
1629
}
1630
1631
void Smt2Printer::toStreamCmdGetProof(std::ostream& out) const
1632
{
1633
  out << "(get-proof)" << std::endl;
1634
}
1635
1636
void Smt2Printer::toStreamCmdGetUnsatAssumptions(std::ostream& out) const
1637
{
1638
  out << "(get-unsat-assumptions)" << std::endl;
1639
}
1640
1641
void Smt2Printer::toStreamCmdGetUnsatCore(std::ostream& out) const
1642
{
1643
  out << "(get-unsat-core)" << std::endl;
1644
}
1645
1646
void Smt2Printer::toStreamCmdSetBenchmarkStatus(std::ostream& out,
1647
                                                Result::Sat status) const
1648
{
1649
  out << "(set-info :status " << status << ')' << std::endl;
1650
}
1651
1652
2
void Smt2Printer::toStreamCmdSetBenchmarkLogic(std::ostream& out,
1653
                                               const std::string& logic) const
1654
{
1655
2
  out << "(set-logic " << logic << ')' << std::endl;
1656
2
}
1657
1658
void Smt2Printer::toStreamCmdSetInfo(std::ostream& out,
1659
                                     const std::string& flag,
1660
                                     const std::string& value) const
1661
{
1662
  out << "(set-info :" << flag << ' ' << value << ')' << std::endl;
1663
}
1664
1665
11
void Smt2Printer::toStreamCmdGetInfo(std::ostream& out,
1666
                                     const std::string& flag) const
1667
{
1668
11
  out << "(get-info :" << flag << ')' << std::endl;
1669
11
}
1670
1671
3
void Smt2Printer::toStreamCmdSetOption(std::ostream& out,
1672
                                       const std::string& flag,
1673
                                       const std::string& value) const
1674
{
1675
3
  out << "(set-option :" << flag << ' ' << value << ')' << std::endl;
1676
3
}
1677
1678
void Smt2Printer::toStreamCmdGetOption(std::ostream& out,
1679
                                       const std::string& flag) const
1680
{
1681
  out << "(get-option :" << flag << ')' << std::endl;
1682
}
1683
1684
void Smt2Printer::toStream(std::ostream& out, const DType& dt) const
1685
{
1686
  for (size_t i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
1687
  {
1688
    const DTypeConstructor& cons = dt[i];
1689
    if (i != 0)
1690
    {
1691
      out << " ";
1692
    }
1693
    out << "(" << cvc5::quoteSymbol(cons.getName());
1694
    for (size_t j = 0, nargs = cons.getNumArgs(); j < nargs; j++)
1695
    {
1696
      const DTypeSelector& arg = cons[j];
1697
      out << " (" << arg.getSelector() << " " << arg.getRangeType() << ")";
1698
    }
1699
    out << ")";
1700
  }
1701
}
1702
1703
void Smt2Printer::toStreamCmdDatatypeDeclaration(
1704
    std::ostream& out, const std::vector<TypeNode>& datatypes) const
1705
{
1706
  Assert(!datatypes.empty());
1707
  Assert(datatypes[0].isDatatype());
1708
  const DType& d0 = datatypes[0].getDType();
1709
  if (d0.isTuple())
1710
  {
1711
    // not necessary to print tuples
1712
    Assert(datatypes.size() == 1);
1713
    return;
1714
  }
1715
  out << "(declare-";
1716
  if (d0.isCodatatype())
1717
  {
1718
    out << "co";
1719
  }
1720
  out << "datatypes";
1721
  out << " (";
1722
  for (const TypeNode& t : datatypes)
1723
  {
1724
    Assert(t.isDatatype());
1725
    const DType& d = t.getDType();
1726
    out << "(" << cvc5::quoteSymbol(d.getName());
1727
    out << " " << d.getNumParameters() << ")";
1728
  }
1729
  out << ") (";
1730
  for (const TypeNode& t : datatypes)
1731
  {
1732
    Assert(t.isDatatype());
1733
    const DType& d = t.getDType();
1734
    if (d.isParametric())
1735
    {
1736
      out << "(par (";
1737
      for (unsigned p = 0, nparam = d.getNumParameters(); p < nparam; p++)
1738
      {
1739
        out << (p > 0 ? " " : "") << d.getParameter(p);
1740
      }
1741
      out << ")";
1742
    }
1743
    out << "(";
1744
    toStream(out, d);
1745
    out << ")";
1746
    if (d.isParametric())
1747
    {
1748
      out << ")";
1749
    }
1750
  }
1751
  out << ")";
1752
  out << ")" << std::endl;
1753
}
1754
1755
1
void Smt2Printer::toStreamCmdComment(std::ostream& out,
1756
                                     const std::string& comment) const
1757
{
1758
2
  std::string s = comment;
1759
1
  size_t pos = 0;
1760
1
  while ((pos = s.find_first_of('"', pos)) != string::npos)
1761
  {
1762
    s.replace(pos, 1, "\"\"");
1763
    pos += 2;
1764
  }
1765
1
  out << "(set-info :notes \"" << s << "\")" << std::endl;
1766
1
}
1767
1768
void Smt2Printer::toStreamCmdDeclareHeap(std::ostream& out,
1769
                                         TypeNode locType,
1770
                                         TypeNode dataType) const
1771
{
1772
  out << "(declare-heap (" << locType << " " << dataType << "))" << std::endl;
1773
}
1774
1775
void Smt2Printer::toStreamCmdEmpty(std::ostream& out,
1776
                                   const std::string& name) const
1777
{
1778
  out << std::endl;
1779
}
1780
1781
void Smt2Printer::toStreamCmdEcho(std::ostream& out,
1782
                                  const std::string& output) const
1783
{
1784
  std::string s = output;
1785
  // escape all double-quotes
1786
  size_t pos = 0;
1787
  while ((pos = s.find('"', pos)) != string::npos)
1788
  {
1789
    s.replace(pos, 1, "\"\"");
1790
    pos += 2;
1791
  }
1792
  out << "(echo \"" << s << "\")" << std::endl;
1793
}
1794
1795
/*
1796
   --------------------------------------------------------------------------
1797
    Handling SyGuS commands
1798
   --------------------------------------------------------------------------
1799
*/
1800
1801
1
static void toStreamSygusGrammar(std::ostream& out, const TypeNode& t)
1802
{
1803
1
  if (!t.isNull() && t.isDatatype() && t.getDType().isSygus())
1804
  {
1805
2
    std::stringstream types_predecl, types_list;
1806
2
    std::set<TypeNode> grammarTypes;
1807
2
    std::list<TypeNode> typesToPrint;
1808
1
    grammarTypes.insert(t);
1809
1
    typesToPrint.push_back(t);
1810
1
    NodeManager* nm = NodeManager::currentNM();
1811
    // for each datatype in grammar
1812
    //   name
1813
    //   sygus type
1814
    //   constructors in order
1815
    do
1816
    {
1817
2
      TypeNode curr = typesToPrint.front();
1818
1
      typesToPrint.pop_front();
1819
1
      Assert(curr.isDatatype() && curr.getDType().isSygus());
1820
1
      const DType& dt = curr.getDType();
1821
1
      types_list << '(' << dt.getName() << ' ' << dt.getSygusType() << " (";
1822
1
      types_predecl << '(' << dt.getName() << ' ' << dt.getSygusType() << ") ";
1823
1
      if (dt.getSygusAllowConst())
1824
      {
1825
        types_list << "(Constant " << dt.getSygusType() << ") ";
1826
      }
1827
2
      for (size_t i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
1828
      {
1829
1
        const DTypeConstructor& cons = dt[i];
1830
        // make a sygus term
1831
2
        std::vector<Node> cchildren;
1832
1
        cchildren.push_back(cons.getConstructor());
1833
1
        for (size_t j = 0, nargs = cons.getNumArgs(); j < nargs; j++)
1834
        {
1835
          TypeNode argType = cons[j].getRangeType();
1836
          std::stringstream ss;
1837
          ss << argType;
1838
          Node bv = nm->mkBoundVar(ss.str(), argType);
1839
          cchildren.push_back(bv);
1840
          // if fresh type, store it for later processing
1841
          if (grammarTypes.insert(argType).second)
1842
          {
1843
            typesToPrint.push_back(argType);
1844
          }
1845
        }
1846
2
        Node consToPrint = nm->mkNode(kind::APPLY_CONSTRUCTOR, cchildren);
1847
        // now, print it using the conversion to builtin with external
1848
3
        types_list << theory::datatypes::utils::sygusToBuiltin(consToPrint,
1849
2
                                                               true);
1850
1
        types_list << ' ';
1851
      }
1852
1
      types_list << "))\n";
1853
1
    } while (!typesToPrint.empty());
1854
1855
1
    out << "\n(" << types_predecl.str() << ")\n(" << types_list.str() << ')';
1856
  }
1857
1
}
1858
1859
2
void Smt2Printer::toStreamCmdSynthFun(std::ostream& out,
1860
                                      Node f,
1861
                                      const std::vector<Node>& vars,
1862
                                      bool isInv,
1863
                                      TypeNode sygusType) const
1864
{
1865
4
  std::stringstream sym;
1866
2
  sym << f;
1867
  out << '(' << (isInv ? "synth-inv " : "synth-fun ")
1868
2
      << cvc5::quoteSymbol(sym.str()) << ' ';
1869
2
  out << '(';
1870
2
  if (!vars.empty())
1871
  {
1872
    // print variable list
1873
2
    std::vector<Node>::const_iterator i = vars.cbegin(), i_end = vars.cend();
1874
2
    out << '(' << *i << ' ' << i->getType() << ')';
1875
2
    ++i;
1876
2
    while (i != i_end)
1877
    {
1878
      out << " (" << *i << ' ' << i->getType() << ')';
1879
      ++i;
1880
    }
1881
  }
1882
2
  out << ')';
1883
  // if not invariant-to-synthesize, print return type
1884
2
  if (!isInv)
1885
  {
1886
2
    TypeNode ftn = f.getType();
1887
2
    TypeNode range = ftn.isFunction() ? ftn.getRangeType() : ftn;
1888
1
    out << ' ' << range;
1889
  }
1890
2
  out << '\n';
1891
  // print grammar, if any
1892
2
  if (!sygusType.isNull())
1893
  {
1894
1
    toStreamSygusGrammar(out, sygusType);
1895
  }
1896
2
  out << ')' << std::endl;
1897
2
}
1898
1899
1
void Smt2Printer::toStreamCmdDeclareVar(std::ostream& out,
1900
                                        Node var,
1901
                                        TypeNode type) const
1902
{
1903
1
  out << "(declare-var " << var << ' ' << type << ')' << std::endl;
1904
1
}
1905
1906
1
void Smt2Printer::toStreamCmdConstraint(std::ostream& out, Node n) const
1907
{
1908
1
  out << "(constraint " << n << ')' << std::endl;
1909
1
}
1910
1911
1
void Smt2Printer::toStreamCmdInvConstraint(
1912
    std::ostream& out, Node inv, Node pre, Node trans, Node post) const
1913
{
1914
2
  out << "(inv-constraint " << inv << ' ' << pre << ' ' << trans << ' ' << post
1915
1
      << ')' << std::endl;
1916
1
}
1917
1918
1
void Smt2Printer::toStreamCmdCheckSynth(std::ostream& out) const
1919
{
1920
1
  out << "(check-synth)" << std::endl;
1921
1
}
1922
1923
void Smt2Printer::toStreamCmdGetAbduct(std::ostream& out,
1924
                                       const std::string& name,
1925
                                       Node conj,
1926
                                       TypeNode sygusType) const
1927
{
1928
  out << "(get-abduct ";
1929
  out << name << ' ';
1930
  out << conj << ' ';
1931
1932
  // print grammar, if any
1933
  if (!sygusType.isNull())
1934
  {
1935
    toStreamSygusGrammar(out, sygusType);
1936
  }
1937
  out << ')' << std::endl;
1938
}
1939
1940
/*
1941
   --------------------------------------------------------------------------
1942
    End of Handling SyGuS commands
1943
   --------------------------------------------------------------------------
1944
*/
1945
1946
template <class T>
1947
static bool tryToStream(std::ostream& out, const Command* c)
1948
{
1949
  if(typeid(*c) == typeid(T)) {
1950
    toStream(out, dynamic_cast<const T*>(c));
1951
    return true;
1952
  }
1953
  return false;
1954
}
1955
1956
template <class T>
1957
static bool tryToStream(std::ostream& out, const Command* c, Variant v)
1958
{
1959
  if(typeid(*c) == typeid(T)) {
1960
    toStream(out, dynamic_cast<const T*>(c), v);
1961
    return true;
1962
  }
1963
  return false;
1964
}
1965
1966
264728
static void toStream(std::ostream& out, const CommandSuccess* s, Variant v)
1967
{
1968
264728
  if(Command::printsuccess::getPrintSuccess(out)) {
1969
18
    out << "success" << endl;
1970
  }
1971
264728
}
1972
1973
static void toStream(std::ostream& out, const CommandInterrupted* s, Variant v)
1974
{
1975
  out << "interrupted" << endl;
1976
}
1977
1978
static void toStream(std::ostream& out, const CommandUnsupported* s, Variant v)
1979
{
1980
#ifdef CVC5_COMPETITION_MODE
1981
  // if in competition mode, lie and say we're ok
1982
  // (we have nothing to lose by saying success, and everything to lose
1983
  // if we say "unsupported")
1984
  out << "success" << endl;
1985
#else  /* CVC5_COMPETITION_MODE */
1986
  out << "unsupported" << endl;
1987
#endif /* CVC5_COMPETITION_MODE */
1988
}
1989
1990
49
static void errorToStream(std::ostream& out, std::string message, Variant v) {
1991
  // escape all double-quotes
1992
49
  size_t pos = 0;
1993
53
  while((pos = message.find('"', pos)) != string::npos) {
1994
2
    message.replace(pos, 1, "\"\"");
1995
2
    pos += 2;
1996
  }
1997
49
  out << "(error \"" << message << "\")" << endl;
1998
49
}
1999
2000
34
static void toStream(std::ostream& out, const CommandFailure* s, Variant v) {
2001
34
  errorToStream(out, s->getMessage(), v);
2002
34
}
2003
2004
15
static void toStream(std::ostream& out, const CommandRecoverableFailure* s,
2005
                     Variant v) {
2006
15
  errorToStream(out, s->getMessage(), v);
2007
15
}
2008
2009
template <class T>
2010
264841
static bool tryToStream(std::ostream& out, const CommandStatus* s, Variant v)
2011
{
2012
264841
  if(typeid(*s) == typeid(T)) {
2013
264777
    toStream(out, dynamic_cast<const T*>(s), v);
2014
264777
    return true;
2015
  }
2016
64
  return false;
2017
}
2018
2019
}  // namespace smt2
2020
}  // namespace printer
2021
29340
}  // namespace cvc5