GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node.h Lines: 291 340 85.6 %
Date: 2021-09-29 Branches: 623 1840 33.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Morgan Deters, Dejan Jovanovic, Aina Niemetz
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
 * Reference-counted encapsulation of a pointer to node information.
14
 */
15
16
#include "cvc5_private.h"
17
18
// circular dependency
19
#include "expr/node_value.h"
20
21
#ifndef CVC5__NODE_H
22
#define CVC5__NODE_H
23
24
#include <iostream>
25
#include <map>
26
#include <string>
27
#include <unordered_map>
28
#include <unordered_set>
29
#include <utility>
30
#include <vector>
31
32
#include "base/check.h"
33
#include "base/exception.h"
34
#include "base/output.h"
35
#include "expr/expr_iomanip.h"
36
#include "expr/kind.h"
37
#include "expr/metakind.h"
38
#include "options/language.h"
39
#include "options/set_language.h"
40
#include "util/hash.h"
41
#include "util/utility.h"
42
43
namespace cvc5 {
44
45
class TypeNode;
46
class NodeManager;
47
48
template <bool ref_count>
49
class NodeTemplate;
50
51
/**
52
 * Exception thrown during the type-checking phase, it can be
53
 * thrown by node.getType().
54
 */
55
class TypeCheckingExceptionPrivate : public Exception {
56
 private:
57
  /** The node responsible for the failure */
58
  NodeTemplate<true>* d_node;
59
60
 public:
61
  /**
62
   * Construct the exception with the problematic node and the message
63
   * @param node the problematic node
64
   * @param message the message explaining the failure
65
   */
66
  TypeCheckingExceptionPrivate(NodeTemplate<false> node, std::string message);
67
68
  /** Destructor */
69
  ~TypeCheckingExceptionPrivate() override;
70
71
  /**
72
   * Get the Node that caused the type-checking to fail.
73
   * @return the node
74
   */
75
  NodeTemplate<true> getNode() const;
76
77
  /**
78
   * Returns the message corresponding to the type-checking failure.
79
   * We prefer toStream() to toString() because that keeps the expr-depth
80
   * and expr-language settings present in the stream.
81
   */
82
  void toStream(std::ostream& out) const override;
83
84
};/* class TypeCheckingExceptionPrivate */
85
86
class UnknownTypeException : public TypeCheckingExceptionPrivate {
87
 public:
88
  UnknownTypeException(NodeTemplate<false> node);
89
};/* class UnknownTypeException */
90
91
/**
92
 * \typedef NodeTemplate<true> Node;
93
 *
94
 * The Node class encapsulates the NodeValue with reference counting.
95
 *
96
 * One should use generally use Nodes to manipulate expressions, to be safe.
97
 * Every outstanding Node that references a NodeValue is counted in that
98
 * NodeValue's reference count.  Reference counts are maintained correctly
99
 * on assignment of the Node object (to point to another NodeValue), and,
100
 * upon destruction of the Node object, the NodeValue's reference count is
101
 * decremented and, if zero, it becomes eligible for reclamation by the
102
 * system.
103
 */
104
typedef NodeTemplate<true> Node;
105
106
/**
107
 * \typedef NodeTemplate<false> TNode;
108
 *
109
 * The TNode class encapsulates the NodeValue but doesn't count references.
110
 *
111
 * TNodes are just like Nodes, but they don't update the reference count.
112
 * Therefore, there is less overhead (copying a TNode is just the cost of
113
 * the underlying pointer copy).  Generally speaking, this is unsafe!
114
 * However, there are certain situations where a TNode can be used safely.
115
 *
116
 * The largest class of uses for TNodes are when you need to use them in a
117
 * "temporary," scoped fashion (hence the "T" in "TNode").  In general,
118
 * it is safe to use TNode as a function parameter type, since the calling
119
 * function (or some other function on the call stack) presumably has a Node
120
 * reference to the expression data.  It is generally _not_ safe, however,
121
 * to return a TNode _from_ a function.  (Functions that return Nodes often
122
 * create the expression they return; such new expressions may not be
123
 * referenced on the call stack, and have a reference count of 1 on
124
 * creation.  If this is returned as a TNode rather than a Node, the
125
 * count drops to zero, marking the expression as eligible for reclamation.)
126
 *
127
 * More guidelines on when to use TNodes is available in the cvc5
128
 * Developer's Guide:
129
 * https://github.com/cvc5/cvc5/wiki/Developer-Guide#dealing-with-expressions-nodes-and-tnodes
130
 */
131
typedef NodeTemplate<false> TNode;
132
133
}  // namespace cvc5
134
135
namespace std {
136
137
template <>
138
struct hash<cvc5::Node>
139
{
140
  size_t operator()(const cvc5::Node& node) const;
141
};
142
143
template <>
144
struct hash<cvc5::TNode>
145
{
146
  size_t operator()(const cvc5::TNode& node) const;
147
};
148
149
}  // namespace std
150
151
namespace cvc5 {
152
namespace expr {
153
154
class NodeValue;
155
156
  namespace attr {
157
    class AttributeManager;
158
    struct SmtAttributes;
159
    }  // namespace attr
160
161
  class ExprSetDepth;
162
  }  // namespace expr
163
164
namespace kind {
165
  namespace metakind {
166
    struct NodeValueConstPrinter;
167
    }  // namespace metakind
168
    }  // namespace kind
169
170
/**
171
 * Encapsulation of an NodeValue pointer.  The reference count is
172
 * maintained in the NodeValue if ref_count is true.
173
 * @param ref_count if true reference are counted in the NodeValue
174
 */
175
template <bool ref_count>
176
class NodeTemplate {
177
  /**
178
   * The NodeValue has access to the private constructors, so that the
179
   * iterators can can create new nodes.
180
   */
181
  friend class expr::NodeValue;
182
183
  /** A convenient null-valued encapsulated pointer */
184
  static NodeTemplate s_null;
185
186
  /** The referenced NodeValue */
187
  expr::NodeValue* d_nv;
188
189
  /**
190
   * This constructor is reserved for use by the NodeTemplate package; one
191
   * must construct an NodeTemplate using one of the build mechanisms of the
192
   * NodeTemplate package.
193
   *
194
   * FIXME: there's a type-system escape here to cast away the const,
195
   * since the refcount needs to be updated.  But conceptually Nodes
196
   * don't change their arguments, and it's nice to have
197
   * const_iterators over them.
198
   *
199
   * This really does needs to be explicit to avoid hard to track errors with
200
   * Nodes implicitly wrapping NodeValues
201
   */
202
  explicit NodeTemplate(const expr::NodeValue*);
203
204
  friend class NodeTemplate<true>;
205
  friend class NodeTemplate<false>;
206
  friend class TypeNode;
207
  friend class NodeManager;
208
209
  friend class NodeBuilder;
210
211
  friend class ::cvc5::expr::attr::AttributeManager;
212
  friend struct ::cvc5::expr::attr::SmtAttributes;
213
214
  friend struct ::cvc5::kind::metakind::NodeValueConstPrinter;
215
216
  /**
217
   * Assigns the expression value and does reference counting. No assumptions
218
   * are made on the expression, and should only be used if we know what we
219
   * are doing.
220
   *
221
   * @param ev the expression value to assign
222
   */
223
  void assignNodeValue(expr::NodeValue* ev);
224
225
  // May throw an AssertionException if the Node is not live, i.e. the ref count
226
  // is not positive.
227
16169208441
  inline void assertTNodeNotExpired() const
228
  {
229
    if(!ref_count) {
230
6789491595
      Assert(d_nv->d_rc > 0) << "TNode pointing to an expired NodeValue";
231
    }
232
16169208441
  }
233
234
public:
235
236
  /**
237
   * Cache-aware, recursive version of substitute() used by the public
238
   * member function with a similar signature.
239
   */
240
 Node substitute(TNode node,
241
                 TNode replacement,
242
                 std::unordered_map<TNode, TNode>& cache) const;
243
244
 /**
245
  * Cache-aware, recursive version of substitute() used by the public
246
  * member function with a similar signature.
247
  */
248
 template <class Iterator1, class Iterator2>
249
 Node substitute(Iterator1 nodesBegin,
250
                 Iterator1 nodesEnd,
251
                 Iterator2 replacementsBegin,
252
                 Iterator2 replacementsEnd,
253
                 std::unordered_map<TNode, TNode>& cache) const;
254
255
 /**
256
  * Cache-aware, recursive version of substitute() used by the public
257
  * member function with a similar signature.
258
  */
259
 template <class Iterator>
260
 Node substitute(Iterator substitutionsBegin,
261
                 Iterator substitutionsEnd,
262
                 std::unordered_map<TNode, TNode>& cache) const;
263
264
 /** Default constructor, makes a null expression.
265
  *
266
  * This constructor is `explicit` to avoid accidentially creating a null node
267
  * from an empty braced-init-list.
268
  */
269
593990906
 explicit NodeTemplate() : d_nv(&expr::NodeValue::null()) {}
270
271
 /**
272
  * Conversion between nodes that are reference-counted and those that are
273
  * not.
274
  * @param node the node to make copy of
275
  */
276
 NodeTemplate(const NodeTemplate<!ref_count>& node);
277
278
 /**
279
  * Copy constructor.  Note that GCC does NOT recognize an instantiation of
280
  * the above template as a copy constructor and problems ensue.  So we
281
  * provide an explicit one here.
282
  * @param node the node to make copy of
283
  */
284
 NodeTemplate(const NodeTemplate& node);
285
286
 /**
287
  * Assignment operator for nodes, copies the relevant information from node
288
  * to this node.
289
  * @param node the node to copy
290
  * @return reference to this node
291
  */
292
 NodeTemplate& operator=(const NodeTemplate& node);
293
294
 /**
295
  * Assignment operator for nodes, copies the relevant information from node
296
  * to this node.
297
  * @param node the node to copy
298
  * @return reference to this node
299
  */
300
 NodeTemplate& operator=(const NodeTemplate<!ref_count>& node);
301
302
 /**
303
  * Destructor. If ref_count is true it will decrement the reference count
304
  * and, if zero, collect the NodeValue.
305
  */
306
 ~NodeTemplate();
307
308
 /**
309
  * Return the null node.
310
  * @return the null node
311
  */
312
296093705
 static NodeTemplate null() { return s_null; }
313
314
 /**
315
  * Returns true if this expression is a null expression.
316
  * @return true if null
317
  */
318
2249676049
 bool isNull() const
319
 {
320
2249676049
   assertTNodeNotExpired();
321
2249676049
   return d_nv == &expr::NodeValue::null();
322
 }
323
324
  /**
325
   * Structural comparison operator for expressions.
326
   * @param node the node to compare to
327
   * @return true if expressions are equal, false otherwise
328
   */
329
  template <bool ref_count_1>
330
2042546824
  bool operator==(const NodeTemplate<ref_count_1>& node) const {
331
2042546824
    assertTNodeNotExpired();
332
2042546824
    node.assertTNodeNotExpired();
333
2042546824
    return d_nv == node.d_nv;
334
  }
335
336
  /**
337
   * Structural comparison operator for expressions.
338
   * @param node the node to compare to
339
   * @return false if expressions are equal, true otherwise
340
   */
341
  template <bool ref_count_1>
342
66224280
  bool operator!=(const NodeTemplate<ref_count_1>& node) const {
343
66224280
    assertTNodeNotExpired();
344
66224280
    node.assertTNodeNotExpired();
345
66224280
    return d_nv != node.d_nv;
346
  }
347
348
  /**
349
   * We compare by expression ids so, keeping things deterministic and having
350
   * that subexpressions have to be smaller than the enclosing expressions.
351
   * @param node the node to compare to
352
   * @return true if this expression is smaller
353
   */
354
  template <bool ref_count_1>
355
858908670
  inline bool operator<(const NodeTemplate<ref_count_1>& node) const {
356
858908670
    assertTNodeNotExpired();
357
858908670
    node.assertTNodeNotExpired();
358
858908670
    return d_nv->d_id < node.d_nv->d_id;
359
  }
360
361
  /**
362
   * We compare by expression ids so, keeping things deterministic and having
363
   * that subexpressions have to be smaller than the enclosing expressions.
364
   * @param node the node to compare to
365
   * @return true if this expression is greater
366
   */
367
  template <bool ref_count_1>
368
561533
  inline bool operator>(const NodeTemplate<ref_count_1>& node) const {
369
561533
    assertTNodeNotExpired();
370
561533
    node.assertTNodeNotExpired();
371
561533
    return d_nv->d_id > node.d_nv->d_id;
372
  }
373
374
  /**
375
   * We compare by expression ids so, keeping things deterministic and having
376
   * that subexpressions have to be smaller than the enclosing expressions.
377
   * @param node the node to compare to
378
   * @return true if this expression is smaller than or equal to
379
   */
380
  template <bool ref_count_1>
381
42
  inline bool operator<=(const NodeTemplate<ref_count_1>& node) const {
382
42
    assertTNodeNotExpired();
383
42
    node.assertTNodeNotExpired();
384
42
    return d_nv->d_id <= node.d_nv->d_id;
385
  }
386
387
  /**
388
   * We compare by expression ids so, keeping things deterministic and having
389
   * that subexpressions have to be smaller than the enclosing expressions.
390
   * @param node the node to compare to
391
   * @return true if this expression is greater than or equal to
392
   */
393
  template <bool ref_count_1>
394
48946
  inline bool operator>=(const NodeTemplate<ref_count_1>& node) const {
395
48946
    assertTNodeNotExpired();
396
48946
    node.assertTNodeNotExpired();
397
48946
    return d_nv->d_id >= node.d_nv->d_id;
398
  }
399
400
  /**
401
   * Returns the i-th child of this node.
402
   * @param i the index of the child
403
   * @return the node representing the i-th child
404
   */
405
632601889
  NodeTemplate operator[](int i) const {
406
632601889
    assertTNodeNotExpired();
407
632601889
    return NodeTemplate(d_nv->getChild(i));
408
  }
409
410
  /**
411
   * Returns true if this node represents a constant
412
   * @return true if const
413
   */
414
  bool isConst() const;
415
416
  /**
417
   * Returns true if this node represents a variable
418
   * @return true if variable
419
   */
420
214237204
  inline bool isVar() const {
421
214237204
    assertTNodeNotExpired();
422
214237204
    return getMetaKind() == kind::metakind::VARIABLE;
423
  }
424
425
  /**
426
   * Returns true if this node represents a nullary operator
427
   */
428
  inline bool isNullaryOp() const {
429
    assertTNodeNotExpired();
430
    return getMetaKind() == kind::metakind::NULLARY_OPERATOR;
431
  }
432
433
  /**
434
   * Returns true if this node represents a closure, that is an expression
435
   * that binds variables.
436
   */
437
29198587
  inline bool isClosure() const {
438
29198587
    assertTNodeNotExpired();
439
58391491
    return getKind() == kind::LAMBDA || getKind() == kind::FORALL
440
29008745
           || getKind() == kind::EXISTS || getKind() == kind::WITNESS
441
29007256
           || getKind() == kind::COMPREHENSION
442
58205562
           || getKind() == kind::MATCH_BIND_CASE;
443
  }
444
445
  /**
446
   * Returns the unique id of this node
447
   * @return the ud
448
   */
449
1445087681
  uint64_t getId() const
450
  {
451
1445087681
    assertTNodeNotExpired();
452
1445087681
    return d_nv->getId();
453
  }
454
455
  /**
456
   * Returns a node representing the operator of this expression.
457
   * If this is an APPLY_UF, then the operator will be a functional term.
458
   * Otherwise, it will be a node with kind BUILTIN.
459
   */
460
  NodeTemplate<true> getOperator() const;
461
462
  /**
463
   * Returns true if the node has an operator (i.e., it's not a
464
   * variable or a constant).
465
   */
466
  inline bool hasOperator() const;
467
468
  /**
469
   * Get the type for the node and optionally do type checking.
470
   *
471
   * Initial type computation will be near-constant time if
472
   * type checking is not requested. Results are memoized, so that
473
   * subsequent calls to getType() without type checking will be
474
   * constant time.
475
   *
476
   * Initial type checking is linear in the size of the expression.
477
   * Again, the results are memoized, so that subsequent calls to
478
   * getType(), with or without type checking, will be constant
479
   * time.
480
   *
481
   * NOTE: A TypeCheckingException can be thrown even when type
482
   * checking is not requested. getType() will always return a
483
   * valid and correct type and, thus, an exception will be thrown
484
   * when no valid or correct type can be computed (e.g., if the
485
   * arguments to a bit-vector operation aren't bit-vectors). When
486
   * type checking is not requested, getType() will do the minimum
487
   * amount of checking required to return a valid result.
488
   *
489
   * @param check whether we should check the type as we compute it
490
   * (default: false)
491
   */
492
  TypeNode getType(bool check = false) const;
493
494
  /**
495
   * Substitution of Nodes.
496
   */
497
  Node substitute(TNode node, TNode replacement) const;
498
499
  /**
500
   * Simultaneous substitution of Nodes.  Elements in the Iterator1
501
   * range will be replaced by their corresponding element in the
502
   * Iterator2 range.  Both ranges should have the same size.
503
   */
504
  template <class Iterator1, class Iterator2>
505
  Node substitute(Iterator1 nodesBegin,
506
                  Iterator1 nodesEnd,
507
                  Iterator2 replacementsBegin,
508
                  Iterator2 replacementsEnd) const;
509
510
  /**
511
   * Simultaneous substitution of Nodes.  Iterators should be over
512
   * pairs (x,y) for the rewrites [x->y].
513
   */
514
  template <class Iterator>
515
  Node substitute(Iterator substitutionsBegin,
516
                  Iterator substitutionsEnd) const;
517
518
  /**
519
   * Simultaneous substitution of Nodes in cache.
520
   */
521
  Node substitute(std::unordered_map<TNode, TNode>& cache) const;
522
523
  /**
524
   * Returns the kind of this node.
525
   * @return the kind
526
   */
527
3233087071
  inline Kind getKind() const {
528
3233087071
    assertTNodeNotExpired();
529
3233087071
    return Kind(d_nv->d_kind);
530
  }
531
532
  /**
533
   * Returns the metakind of this node.
534
   * @return the metakind
535
   */
536
435839274
  inline kind::MetaKind getMetaKind() const {
537
435839274
    assertTNodeNotExpired();
538
435839274
    return kind::metaKindOf(getKind());
539
  }
540
541
  /**
542
   * Returns the number of children this node has.
543
   * @return the number of children
544
   */
545
  inline size_t getNumChildren() const;
546
547
  /**
548
   * If this is a CONST_* Node, extract the constant from it.
549
   */
550
  template <class T>
551
  inline const T& getConst() const;
552
553
  /**
554
   * Returns the reference count of this node.
555
   * @return the refcount
556
   */
557
  unsigned getRefCount() const {
558
    return d_nv->getRefCount();
559
  }
560
561
  /**
562
   * Returns the value of the given attribute that this has been attached.
563
   * @param attKind the kind of the attribute
564
   * @return the value of the attribute
565
   */
566
  template <class AttrKind>
567
  inline typename AttrKind::value_type getAttribute(const AttrKind& attKind) const;
568
569
  // Note that there are two, distinct hasAttribute() declarations for
570
  // a reason (rather than using a pointer-valued argument with a
571
  // default value): they permit more optimized code in the underlying
572
  // hasAttribute() implementations.
573
574
  /**
575
   * Returns true if this node has been associated an attribute of given kind.
576
   * Additionaly, if a pointer to the value_kind is give, and the attribute
577
   * value has been set for this node, it will be returned.
578
   * @param attKind the kind of the attribute
579
   * @return true if this node has the requested attribute
580
   */
581
  template <class AttrKind>
582
  inline bool hasAttribute(const AttrKind& attKind) const;
583
584
  /**
585
   * Returns true if this node has been associated an attribute of given kind.
586
   * Additionaly, if a pointer to the value_kind is give, and the attribute
587
   * value has been set for this node, it will be returned.
588
   * @param attKind the kind of the attribute
589
   * @param value where to store the value if it exists
590
   * @return true if this node has the requested attribute
591
   */
592
  template <class AttrKind>
593
  inline bool getAttribute(const AttrKind& attKind,
594
                           typename AttrKind::value_type& value) const;
595
596
  /**
597
   * Sets the given attribute of this node to the given value.
598
   * @param attKind the kind of the atribute
599
   * @param value the value to set the attribute to
600
   */
601
  template <class AttrKind>
602
  inline void setAttribute(const AttrKind& attKind,
603
                           const typename AttrKind::value_type& value);
604
605
  /** Iterator allowing for scanning through the children. */
606
  typedef typename expr::NodeValue::iterator< NodeTemplate<ref_count> > iterator;
607
  /** Constant iterator allowing for scanning through the children. */
608
  using const_iterator =
609
      typename expr::NodeValue::iterator<NodeTemplate<ref_count>>;
610
  /**
611
   * Reverse constant iterator allowing for scanning through the children in
612
   * reverse order.
613
   */
614
  using const_reverse_iterator = std::reverse_iterator<
615
      typename expr::NodeValue::iterator<NodeTemplate<ref_count>>>;
616
617
18
  class kinded_iterator {
618
    friend class NodeTemplate<ref_count>;
619
620
    NodeTemplate<ref_count> d_node;
621
    ssize_t d_child;
622
623
8
    kinded_iterator(TNode node, ssize_t child) :
624
      d_node(node),
625
8
      d_child(child) {
626
8
    }
627
628
    // These are factories to serve as clients to Node::begin<K>() and
629
    // Node::end<K>().
630
4
    static kinded_iterator begin(TNode n, Kind k) {
631
4
      return kinded_iterator(n, n.getKind() == k ? 0 : -2);
632
    }
633
4
    static kinded_iterator end(TNode n, Kind k) {
634
4
      return kinded_iterator(n, n.getKind() == k ? n.getNumChildren() : -1);
635
    }
636
637
  public:
638
    typedef NodeTemplate<ref_count> value_type;
639
    typedef std::ptrdiff_t difference_type;
640
    typedef NodeTemplate<ref_count>* pointer;
641
    typedef NodeTemplate<ref_count>& reference;
642
643
    kinded_iterator() :
644
      d_node(NodeTemplate<ref_count>::null()),
645
      d_child(-2) {
646
    }
647
648
8
    kinded_iterator(const kinded_iterator& i) :
649
      d_node(i.d_node),
650
8
      d_child(i.d_child) {
651
8
    }
652
653
8
    NodeTemplate<ref_count> operator*() {
654
8
      return d_child < 0 ? d_node : d_node[d_child];
655
    }
656
657
4
    bool operator==(const kinded_iterator& i) {
658
4
      return d_node == i.d_node && d_child == i.d_child;
659
    }
660
661
    bool operator!=(const kinded_iterator& i) {
662
      return !(*this == i);
663
    }
664
665
8
    kinded_iterator& operator++() {
666
8
      if(d_child != -1) {
667
8
        ++d_child;
668
      }
669
8
      return *this;
670
    }
671
672
8
    kinded_iterator operator++(int) {
673
8
      kinded_iterator i = *this;
674
8
      ++*this;
675
8
      return i;
676
    }
677
  };/* class NodeTemplate<ref_count>::kinded_iterator */
678
679
  typedef kinded_iterator const_kinded_iterator;
680
681
  /**
682
   * Returns the iterator pointing to the first child.
683
   * @return the iterator
684
   */
685
78533566
  inline iterator begin() {
686
78533566
    assertTNodeNotExpired();
687
78533566
    return d_nv->begin< NodeTemplate<ref_count> >();
688
  }
689
690
  /**
691
   * Returns the iterator pointing to the end of the children (one beyond the
692
   * last one).
693
   * @return the end of the children iterator.
694
   */
695
389208053
  inline iterator end() {
696
389208053
    assertTNodeNotExpired();
697
389208053
    return d_nv->end< NodeTemplate<ref_count> >();
698
  }
699
700
  /**
701
   * Returns the iterator pointing to the first child, if the node's
702
   * kind is the same as the parameter, otherwise returns the iterator
703
   * pointing to the node itself.  This is useful if you want to
704
   * pretend to iterate over a "unary" PLUS, for instance, since unary
705
   * PLUSes don't exist---begin(PLUS) will give an iterator over the
706
   * children if the node's a PLUS node, otherwise give an iterator
707
   * over the node itself, as if it were a unary PLUS.
708
   * @param kind the kind to match
709
   * @return the kinded_iterator iterating over this Node (if its kind
710
   * is not the passed kind) or its children
711
   */
712
4
  inline kinded_iterator begin(Kind kind) {
713
4
    assertTNodeNotExpired();
714
4
    return kinded_iterator::begin(*this, kind);
715
  }
716
717
  /**
718
   * Returns the iterator pointing to the end of the children (one
719
   * beyond the last one), if the node's kind is the same as the
720
   * parameter, otherwise returns the iterator pointing to the
721
   * one-of-the-node-itself.  This is useful if you want to pretend to
722
   * iterate over a "unary" PLUS, for instance, since unary PLUSes
723
   * don't exist---begin(PLUS) will give an iterator over the children
724
   * if the node's a PLUS node, otherwise give an iterator over the
725
   * node itself, as if it were a unary PLUS.
726
   * @param kind the kind to match
727
   * @return the kinded_iterator pointing off-the-end of this Node (if
728
   * its kind is not the passed kind) or off-the-end of its children
729
   */
730
4
  inline kinded_iterator end(Kind kind) {
731
4
    assertTNodeNotExpired();
732
4
    return kinded_iterator::end(*this, kind);
733
  }
734
735
  /**
736
   * Returns the const_iterator pointing to the first child.
737
   * @return the const_iterator
738
   */
739
49092148
  const_iterator begin() const
740
  {
741
49092148
    assertTNodeNotExpired();
742
49092148
    return d_nv->begin< NodeTemplate<ref_count> >();
743
  }
744
745
  /**
746
   * Returns the const_iterator pointing to the end of the children (one
747
   * beyond the last one.
748
   * @return the end of the children const_iterator.
749
   */
750
44036687
  const_iterator end() const
751
  {
752
44036687
    assertTNodeNotExpired();
753
44036687
    return d_nv->end< NodeTemplate<ref_count> >();
754
  }
755
756
  /**
757
   * Returns the const_reverse_iterator pointing to the last child.
758
   * @return the const_reverse_iterator
759
   */
760
2
  const_reverse_iterator rbegin() const
761
  {
762
2
    assertTNodeNotExpired();
763
2
    return std::make_reverse_iterator(d_nv->end<NodeTemplate<ref_count>>());
764
  }
765
766
  /**
767
   * Returns the const_reverse_iterator pointing to one before the first child.
768
   * @return the end of the const_reverse_iterator.
769
   */
770
2
  const_reverse_iterator rend() const
771
  {
772
2
    assertTNodeNotExpired();
773
2
    return std::make_reverse_iterator(d_nv->begin<NodeTemplate<ref_count>>());
774
  }
775
776
  /**
777
   * Returns the iterator pointing to the first child, if the node's
778
   * kind is the same as the parameter, otherwise returns the iterator
779
   * pointing to the node itself.  This is useful if you want to
780
   * pretend to iterate over a "unary" PLUS, for instance, since unary
781
   * PLUSes don't exist---begin(PLUS) will give an iterator over the
782
   * children if the node's a PLUS node, otherwise give an iterator
783
   * over the node itself, as if it were a unary PLUS.
784
   * @param kind the kind to match
785
   * @return the kinded_iterator iterating over this Node (if its kind
786
   * is not the passed kind) or its children
787
   */
788
  inline const_kinded_iterator begin(Kind kind) const {
789
    assertTNodeNotExpired();
790
    return const_kinded_iterator::begin(*this, kind);
791
  }
792
793
  /**
794
   * Returns the iterator pointing to the end of the children (one
795
   * beyond the last one), if the node's kind is the same as the
796
   * parameter, otherwise returns the iterator pointing to the
797
   * one-of-the-node-itself.  This is useful if you want to pretend to
798
   * iterate over a "unary" PLUS, for instance, since unary PLUSes
799
   * don't exist---begin(PLUS) will give an iterator over the children
800
   * if the node's a PLUS node, otherwise give an iterator over the
801
   * node itself, as if it were a unary PLUS.
802
   * @param kind the kind to match
803
   * @return the kinded_iterator pointing off-the-end of this Node (if
804
   * its kind is not the passed kind) or off-the-end of its children
805
   */
806
  inline const_kinded_iterator end(Kind kind) const {
807
    assertTNodeNotExpired();
808
    return const_kinded_iterator::end(*this, kind);
809
  }
810
811
  /**
812
   * Converts this node into a string representation.
813
   * @return the string representation of this node.
814
   */
815
4257
  inline std::string toString() const {
816
4257
    assertTNodeNotExpired();
817
4257
    return d_nv->toString();
818
  }
819
820
  /**
821
   * Converts this node into a string representation and sends it to the
822
   * given stream
823
   *
824
   * @param out the stream to serialize this node to
825
   * @param toDepth the depth to which to print this expression, or -1 to
826
   * print it fully
827
   * @param language the language in which to output
828
   */
829
18539
  inline void toStream(std::ostream& out,
830
                       int toDepth = -1,
831
                       size_t dagThreshold = 1,
832
                       Language language = Language::LANG_AUTO) const
833
  {
834
18539
    assertTNodeNotExpired();
835
18539
    d_nv->toStream(out, toDepth, dagThreshold, language);
836
18525
  }
837
838
  /**
839
   * IOStream manipulator to set the maximum depth of Nodes when
840
   * pretty-printing.  -1 means print to any depth.  E.g.:
841
   *
842
   *   // let a, b, c, and d be VARIABLEs
843
   *   Node n = nm->mkNode(OR, a, b, nm->mkNode(AND, c, nm->mkNode(NOT, d)))
844
   *   out << setdepth(3) << n;
845
   *
846
   * gives "(OR a b (AND c (NOT d)))", but
847
   *
848
   *   out << setdepth(1) << [same node as above]
849
   *
850
   * gives "(OR a b (...))"
851
   */
852
  typedef expr::ExprSetDepth setdepth;
853
854
  /**
855
   * IOStream manipulator to print expressions as DAGs (or not).
856
   */
857
  typedef expr::ExprDag dag;
858
859
  /**
860
   * IOStream manipulator to set the output language for Exprs.
861
   */
862
  typedef language::SetLanguage setlanguage;
863
864
  /**
865
   * Very basic pretty printer for Node.
866
   * @param out output stream to print to.
867
   * @param indent number of spaces to indent the formula by.
868
   */
869
  inline void printAst(std::ostream& out, int indent = 0) const;
870
871
  template <bool ref_count2>
872
  NodeTemplate<true> eqNode(const NodeTemplate<ref_count2>& right) const;
873
874
  NodeTemplate<true> notNode() const;
875
  NodeTemplate<true> negate() const;
876
  template <bool ref_count2>
877
  NodeTemplate<true> andNode(const NodeTemplate<ref_count2>& right) const;
878
  template <bool ref_count2>
879
  NodeTemplate<true> orNode(const NodeTemplate<ref_count2>& right) const;
880
  template <bool ref_count2, bool ref_count3>
881
  NodeTemplate<true> iteNode(const NodeTemplate<ref_count2>& thenpart,
882
                             const NodeTemplate<ref_count3>& elsepart) const;
883
  template <bool ref_count2>
884
  NodeTemplate<true> impNode(const NodeTemplate<ref_count2>& right) const;
885
  template <bool ref_count2>
886
  NodeTemplate<true> xorNode(const NodeTemplate<ref_count2>& right) const;
887
888
};/* class NodeTemplate<ref_count> */
889
890
/**
891
 * Serializes a given node to the given stream.
892
 *
893
 * @param out the output stream to use
894
 * @param n the node to output to the stream
895
 * @return the stream
896
 */
897
17204
inline std::ostream& operator<<(std::ostream& out, TNode n) {
898
34408
  n.toStream(out,
899
17204
             Node::setdepth::getDepth(out),
900
             Node::dag::getDag(out),
901
             Node::setlanguage::getLanguage(out));
902
17190
  return out;
903
}
904
905
/**
906
 * Serialize a vector of nodes to given stream.
907
 *
908
 * @param out the output stream to use
909
 * @param container the vector of nodes to output to the stream
910
 * @return the stream
911
 */
912
template <bool RC>
913
std::ostream& operator<<(std::ostream& out,
914
                         const std::vector<NodeTemplate<RC>>& container)
915
{
916
  container_to_stream(out, container);
917
  return out;
918
}
919
920
/**
921
 * Serialize a set of nodes to the given stream.
922
 *
923
 * @param out the output stream to use
924
 * @param container the set of nodes to output to the stream
925
 * @return the stream
926
 */
927
template <bool RC>
928
std::ostream& operator<<(std::ostream& out,
929
                         const std::set<NodeTemplate<RC>>& container)
930
{
931
  container_to_stream(out, container);
932
  return out;
933
}
934
935
/**
936
 * Serialize an unordered_set of nodes to the given stream.
937
 *
938
 * @param out the output stream to use
939
 * @param container the unordered_set of nodes to output to the stream
940
 * @return the stream
941
 */
942
template <bool RC, typename hash_function>
943
std::ostream& operator<<(
944
    std::ostream& out,
945
    const std::unordered_set<NodeTemplate<RC>, hash_function>& container)
946
{
947
  container_to_stream(out, container);
948
  return out;
949
}
950
951
/**
952
 * Serialize a map of nodes to the given stream.
953
 *
954
 * @param out the output stream to use
955
 * @param container the map of nodes to output to the stream
956
 * @return the stream
957
 */
958
template <bool RC, typename V>
959
std::ostream& operator<<(
960
    std::ostream& out,
961
    const std::map<NodeTemplate<RC>, V>& container)
962
{
963
  container_to_stream(out, container);
964
  return out;
965
}
966
967
/**
968
 * Serialize an unordered_map of nodes to the given stream.
969
 *
970
 * @param out the output stream to use
971
 * @param container the unordered_map of nodes to output to the stream
972
 * @return the stream
973
 */
974
template <bool RC, typename V, typename HF>
975
std::ostream& operator<<(
976
    std::ostream& out,
977
    const std::unordered_map<NodeTemplate<RC>, V, HF>& container)
978
{
979
  container_to_stream(out, container);
980
  return out;
981
}
982
983
}  // namespace cvc5
984
985
//#include "expr/attribute.h"
986
#include "expr/node_manager.h"
987
988
namespace cvc5 {
989
990
using TNodePairHashFunction =
991
    PairHashFunction<TNode, TNode, std::hash<TNode>, std::hash<TNode>>;
992
993
template <bool ref_count>
994
433077298
inline size_t NodeTemplate<ref_count>::getNumChildren() const {
995
433077298
  assertTNodeNotExpired();
996
433077298
  return d_nv->getNumChildren();
997
}
998
999
template <bool ref_count>
1000
template <class T>
1001
293505180
inline const T& NodeTemplate<ref_count>::getConst() const {
1002
293505180
  assertTNodeNotExpired();
1003
293505180
  return d_nv->getConst<T>();
1004
}
1005
1006
template <bool ref_count>
1007
template <class AttrKind>
1008
126729472
inline typename AttrKind::value_type NodeTemplate<ref_count>::
1009
getAttribute(const AttrKind&) const {
1010
126729472
  assertTNodeNotExpired();
1011
1012
126729472
  return NodeManager::currentNM()->getAttribute(*this, AttrKind());
1013
}
1014
1015
template <bool ref_count>
1016
template <class AttrKind>
1017
111952173
inline bool NodeTemplate<ref_count>::
1018
hasAttribute(const AttrKind&) const {
1019
111952173
  assertTNodeNotExpired();
1020
1021
111952173
  return NodeManager::currentNM()->hasAttribute(*this, AttrKind());
1022
}
1023
1024
template <bool ref_count>
1025
template <class AttrKind>
1026
58771111
inline bool NodeTemplate<ref_count>::getAttribute(const AttrKind&,
1027
                                                  typename AttrKind::value_type& ret) const {
1028
58771111
  assertTNodeNotExpired();
1029
1030
58771111
  return NodeManager::currentNM()->getAttribute(*this, AttrKind(), ret);
1031
}
1032
1033
template <bool ref_count>
1034
template <class AttrKind>
1035
27790942
inline void NodeTemplate<ref_count>::
1036
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) {
1037
27790942
  assertTNodeNotExpired();
1038
1039
27790942
  NodeManager::currentNM()->setAttribute(*this, AttrKind(), value);
1040
27790942
}
1041
1042
template <bool ref_count>
1043
3351846
NodeTemplate<ref_count> NodeTemplate<ref_count>::s_null(&expr::NodeValue::null());
1044
1045
// FIXME: escape from type system convenient but is there a better
1046
// way?  Nodes conceptually don't change their expr values but of
1047
// course they do modify the refcount.  But it's nice to be able to
1048
// support node_iterators over const NodeValue*.  So.... hm.
1049
template <bool ref_count>
1050
1248763489
NodeTemplate<ref_count>::NodeTemplate(const expr::NodeValue* ev) :
1051
1248763489
  d_nv(const_cast<expr::NodeValue*> (ev)) {
1052
1248763489
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1053
  if(ref_count) {
1054
698281378
    d_nv->inc();
1055
  } else {
1056
550482111
    Assert(d_nv->d_rc > 0 || d_nv == &expr::NodeValue::null())
1057
        << "TNode constructed from NodeValue with rc == 0";
1058
  }
1059
1248763489
}
1060
1061
// the code for these two following constructors ("conversion/copy
1062
// constructors") is identical, but we need both.  see comment in the
1063
// class.
1064
1065
template <bool ref_count>
1066
2824933898
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate<!ref_count>& e) {
1067
2824933898
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1068
2824933898
  d_nv = e.d_nv;
1069
  if(ref_count) {
1070
993301433
    Assert(d_nv->d_rc > 0) << "Node constructed from TNode with rc == 0";
1071
993301433
    d_nv->inc();
1072
  } else {
1073
    // shouldn't ever fail
1074
1831632465
    Assert(d_nv->d_rc > 0) << "TNode constructed from Node with rc == 0";
1075
  }
1076
2824933898
}
1077
1078
template <bool ref_count>
1079
10661424005
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate& e) {
1080
10661424005
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1081
10661424005
  d_nv = e.d_nv;
1082
  if(ref_count) {
1083
    // shouldn't ever fail
1084
5949247606
    Assert(d_nv->d_rc > 0) << "Node constructed from Node with rc == 0";
1085
5949247606
    d_nv->inc();
1086
  } else {
1087
4712176399
    Assert(d_nv->d_rc > 0) << "TNode constructed from TNode with rc == 0";
1088
  }
1089
10661424005
}
1090
1091
template <bool ref_count>
1092
15329104864
NodeTemplate<ref_count>::~NodeTemplate() {
1093
15329104864
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1094
  if(ref_count) {
1095
    // shouldn't ever fail
1096
8126623694
    Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1097
8126623694
    d_nv->dec();
1098
  }
1099
15329104864
}
1100
1101
template <bool ref_count>
1102
void NodeTemplate<ref_count>::assignNodeValue(expr::NodeValue* ev) {
1103
  d_nv = ev;
1104
  if(ref_count) {
1105
    d_nv->inc();
1106
  } else {
1107
    Assert(d_nv->d_rc > 0) << "TNode assigned to NodeValue with rc == 0";
1108
  }
1109
}
1110
1111
template <bool ref_count>
1112
742489755
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1113
operator=(const NodeTemplate& e) {
1114
742489755
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1115
742489755
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1116
742489755
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1117
    if(ref_count) {
1118
      // shouldn't ever fail
1119
343983774
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1120
343983774
      d_nv->dec();
1121
    }
1122
457058417
    d_nv = e.d_nv;
1123
    if(ref_count) {
1124
      // shouldn't ever fail
1125
343983774
      Assert(d_nv->d_rc > 0) << "Node assigned from Node with rc == 0";
1126
343983774
      d_nv->inc();
1127
    } else {
1128
113074643
      Assert(d_nv->d_rc > 0) << "TNode assigned from TNode with rc == 0";
1129
    }
1130
  }
1131
742489755
  return *this;
1132
}
1133
1134
template <bool ref_count>
1135
57382351
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1136
operator=(const NodeTemplate<!ref_count>& e) {
1137
57382351
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1138
57382351
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1139
57382351
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1140
    if(ref_count) {
1141
      // shouldn't ever fail
1142
7072719
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1143
7072719
      d_nv->dec();
1144
    }
1145
56069398
    d_nv = e.d_nv;
1146
    if(ref_count) {
1147
7072719
      Assert(d_nv->d_rc > 0) << "Node assigned from TNode with rc == 0";
1148
7072719
      d_nv->inc();
1149
    } else {
1150
      // shouldn't ever happen
1151
48996679
      Assert(d_nv->d_rc > 0) << "TNode assigned from Node with rc == 0";
1152
    }
1153
  }
1154
57382351
  return *this;
1155
}
1156
1157
template <bool ref_count>
1158
template <bool ref_count2>
1159
NodeTemplate<true>
1160
8694155
NodeTemplate<ref_count>::eqNode(const NodeTemplate<ref_count2>& right) const {
1161
8694155
  assertTNodeNotExpired();
1162
8694155
  return NodeManager::currentNM()->mkNode(kind::EQUAL, *this, right);
1163
}
1164
1165
template <bool ref_count>
1166
10334243
NodeTemplate<true> NodeTemplate<ref_count>::notNode() const {
1167
10334243
  assertTNodeNotExpired();
1168
10334243
  return NodeManager::currentNM()->mkNode(kind::NOT, *this);
1169
}
1170
1171
template <bool ref_count>
1172
5987865
NodeTemplate<true> NodeTemplate<ref_count>::negate() const {
1173
5987865
  assertTNodeNotExpired();
1174
5987865
  return (getKind() == kind::NOT) ? NodeTemplate<true>(d_nv->getChild(0)) : NodeManager::currentNM()->mkNode(kind::NOT, *this);
1175
}
1176
1177
template <bool ref_count>
1178
template <bool ref_count2>
1179
NodeTemplate<true>
1180
91914
NodeTemplate<ref_count>::andNode(const NodeTemplate<ref_count2>& right) const {
1181
91914
  assertTNodeNotExpired();
1182
91914
  return NodeManager::currentNM()->mkNode(kind::AND, *this, right);
1183
}
1184
1185
template <bool ref_count>
1186
template <bool ref_count2>
1187
NodeTemplate<true>
1188
46968
NodeTemplate<ref_count>::orNode(const NodeTemplate<ref_count2>& right) const {
1189
46968
  assertTNodeNotExpired();
1190
46968
  return NodeManager::currentNM()->mkNode(kind::OR, *this, right);
1191
}
1192
1193
template <bool ref_count>
1194
template <bool ref_count2, bool ref_count3>
1195
NodeTemplate<true>
1196
133142
NodeTemplate<ref_count>::iteNode(const NodeTemplate<ref_count2>& thenpart,
1197
                                 const NodeTemplate<ref_count3>& elsepart) const {
1198
133142
  assertTNodeNotExpired();
1199
133142
  return NodeManager::currentNM()->mkNode(kind::ITE, *this, thenpart, elsepart);
1200
}
1201
1202
template <bool ref_count>
1203
template <bool ref_count2>
1204
NodeTemplate<true>
1205
66528
NodeTemplate<ref_count>::impNode(const NodeTemplate<ref_count2>& right) const {
1206
66528
  assertTNodeNotExpired();
1207
66528
  return NodeManager::currentNM()->mkNode(kind::IMPLIES, *this, right);
1208
}
1209
1210
template <bool ref_count>
1211
template <bool ref_count2>
1212
NodeTemplate<true>
1213
92
NodeTemplate<ref_count>::xorNode(const NodeTemplate<ref_count2>& right) const {
1214
92
  assertTNodeNotExpired();
1215
92
  return NodeManager::currentNM()->mkNode(kind::XOR, *this, right);
1216
}
1217
1218
template <bool ref_count>
1219
inline void
1220
NodeTemplate<ref_count>::printAst(std::ostream& out, int indent) const {
1221
  assertTNodeNotExpired();
1222
  d_nv->printAst(out, indent);
1223
}
1224
1225
/**
1226
 * Returns a node representing the operator of this expression.
1227
 * If this is an APPLY_UF, then the operator will be a functional term.
1228
 * Otherwise, it will be a node with kind BUILTIN.
1229
 */
1230
template <bool ref_count>
1231
18946287
NodeTemplate<true> NodeTemplate<ref_count>::getOperator() const
1232
{
1233
18946287
  assertTNodeNotExpired();
1234
1235
18946287
  kind::MetaKind mk = getMetaKind();
1236
18946287
  if (mk == kind::metakind::OPERATOR)
1237
  {
1238
    /* Returns a BUILTIN node. */
1239
3789722
    return NodeManager::currentNM()->operatorOf(getKind());
1240
  }
1241
15156565
  Assert(mk == kind::metakind::PARAMETERIZED);
1242
  /* The operator is the first child. */
1243
15156565
  return Node(d_nv->d_children[0]);
1244
}
1245
1246
/**
1247
 * Returns true if the node has an operator (i.e., it's not a variable
1248
 * or a constant).
1249
 */
1250
template <bool ref_count>
1251
6252953
inline bool NodeTemplate<ref_count>::hasOperator() const {
1252
6252953
  assertTNodeNotExpired();
1253
6252953
  return NodeManager::hasOperator(getKind());
1254
}
1255
1256
template <bool ref_count>
1257
274950735
TypeNode NodeTemplate<ref_count>::getType(bool check) const
1258
{
1259
274950735
  assertTNodeNotExpired();
1260
1261
274950735
  return NodeManager::currentNM()->getType(*this, check);
1262
}
1263
1264
template <bool ref_count>
1265
inline Node
1266
24574
NodeTemplate<ref_count>::substitute(TNode node, TNode replacement) const {
1267
24574
  if (node == *this) {
1268
3979
    return replacement;
1269
  }
1270
41190
  std::unordered_map<TNode, TNode> cache;
1271
20595
  return substitute(node, replacement, cache);
1272
}
1273
1274
template <bool ref_count>
1275
4089694
Node NodeTemplate<ref_count>::substitute(
1276
    TNode node,
1277
    TNode replacement,
1278
    std::unordered_map<TNode, TNode>& cache) const
1279
{
1280
4089694
  Assert(node != *this);
1281
1282
4089694
  if (getNumChildren() == 0 || node == replacement)
1283
  {
1284
932506
    return *this;
1285
  }
1286
1287
  // in cache?
1288
3157188
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1289
      cache.find(*this);
1290
3157188
  if(i != cache.end()) {
1291
1497645
    return (*i).second;
1292
  }
1293
1294
  // otherwise compute
1295
3319086
  NodeBuilder nb(getKind());
1296
1659543
  if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1297
    // push the operator
1298
681895
    if(getOperator() == node) {
1299
98
      nb << replacement;
1300
    } else {
1301
681797
      nb << getOperator().substitute(node, replacement, cache);
1302
    }
1303
  }
1304
5141698
  for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1305
  {
1306
3482155
    if (*it == node)
1307
    {
1308
512574
      nb << replacement;
1309
    }
1310
    else
1311
    {
1312
2969581
      nb << (*it).substitute(node, replacement, cache);
1313
    }
1314
  }
1315
1316
  // put in cache
1317
3319086
  Node n = nb;
1318
1659543
  cache[*this] = n;
1319
1659543
  return n;
1320
}
1321
1322
template <bool ref_count>
1323
template <class Iterator1, class Iterator2>
1324
inline Node
1325
9262041
NodeTemplate<ref_count>::substitute(Iterator1 nodesBegin,
1326
                                    Iterator1 nodesEnd,
1327
                                    Iterator2 replacementsBegin,
1328
                                    Iterator2 replacementsEnd) const {
1329
18524082
  std::unordered_map<TNode, TNode> cache;
1330
  return substitute(nodesBegin, nodesEnd,
1331
18524082
                    replacementsBegin, replacementsEnd, cache);
1332
}
1333
1334
template <bool ref_count>
1335
template <class Iterator1, class Iterator2>
1336
38291775
Node NodeTemplate<ref_count>::substitute(
1337
    Iterator1 nodesBegin,
1338
    Iterator1 nodesEnd,
1339
    Iterator2 replacementsBegin,
1340
    Iterator2 replacementsEnd,
1341
    std::unordered_map<TNode, TNode>& cache) const
1342
{
1343
  // in cache?
1344
38291775
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1345
      cache.find(*this);
1346
38291775
  if(i != cache.end()) {
1347
10769137
    return (*i).second;
1348
  }
1349
1350
  // otherwise compute
1351
27522638
  Assert(std::distance(nodesBegin, nodesEnd)
1352
         == std::distance(replacementsBegin, replacementsEnd))
1353
      << "Substitution iterator ranges must be equal size";
1354
27522638
  Iterator1 j = std::find(nodesBegin, nodesEnd, TNode(*this));
1355
27522638
  if(j != nodesEnd) {
1356
2406844
    Iterator2 b = replacementsBegin;
1357
2406844
    std::advance(b, std::distance(nodesBegin, j));
1358
4813688
    Node n = *b;
1359
2406844
    cache[*this] = n;
1360
2406844
    return n;
1361
25115794
  } else if(getNumChildren() == 0) {
1362
13621535
    cache[*this] = *this;
1363
13621535
    return *this;
1364
  } else {
1365
22988518
    NodeBuilder nb(getKind());
1366
11494259
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1367
      // push the operator
1368
499163
      nb << getOperator().substitute(nodesBegin, nodesEnd,
1369
                                     replacementsBegin, replacementsEnd,
1370
                                     cache);
1371
    }
1372
40024830
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1373
    {
1374
28530571
      nb << (*it).substitute(
1375
          nodesBegin, nodesEnd, replacementsBegin, replacementsEnd, cache);
1376
    }
1377
22988518
    Node n = nb;
1378
11494259
    cache[*this] = n;
1379
11494259
    return n;
1380
  }
1381
}
1382
1383
template <bool ref_count>
1384
template <class Iterator>
1385
inline Node
1386
33006
NodeTemplate<ref_count>::substitute(Iterator substitutionsBegin,
1387
                                    Iterator substitutionsEnd) const {
1388
66012
  std::unordered_map<TNode, TNode> cache;
1389
66012
  return substitute(substitutionsBegin, substitutionsEnd, cache);
1390
}
1391
1392
template <bool ref_count>
1393
6
inline Node NodeTemplate<ref_count>::substitute(
1394
    std::unordered_map<TNode, TNode>& cache) const
1395
{
1396
  // Since no substitution is given (other than what may already be in the
1397
  // cache), we pass dummy iterators to conform to the main substitute method,
1398
  // giving the same value to substitutionsBegin and substitutionsEnd.
1399
6
  return substitute(cache.cend(), cache.cend(), cache);
1400
}
1401
1402
template <bool ref_count>
1403
template <class Iterator>
1404
61173
Node NodeTemplate<ref_count>::substitute(
1405
    Iterator substitutionsBegin,
1406
    Iterator substitutionsEnd,
1407
    std::unordered_map<TNode, TNode>& cache) const
1408
{
1409
  // in cache?
1410
61173
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1411
      cache.find(*this);
1412
61173
  if(i != cache.end()) {
1413
330
    return (*i).second;
1414
  }
1415
1416
  // otherwise compute
1417
60843
  Iterator j = find_if(
1418
      substitutionsBegin,
1419
      substitutionsEnd,
1420
1349689
      [this](const auto& subst){ return subst.first == *this; });
1421
60843
  if(j != substitutionsEnd) {
1422
58994
    Node n = (*j).second;
1423
29497
    cache[*this] = n;
1424
29497
    return n;
1425
31346
  } else if(getNumChildren() == 0) {
1426
17887
    cache[*this] = *this;
1427
17887
    return *this;
1428
  } else {
1429
26918
    NodeBuilder nb(getKind());
1430
13459
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1431
      // push the operator
1432
102
      nb << getOperator().substitute(substitutionsBegin, substitutionsEnd, cache);
1433
    }
1434
41518
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1435
    {
1436
28059
      nb << (*it).substitute(substitutionsBegin, substitutionsEnd, cache);
1437
    }
1438
26918
    Node n = nb;
1439
13459
    cache[*this] = n;
1440
13459
    return n;
1441
  }
1442
}
1443
1444
#ifdef CVC5_DEBUG
1445
/**
1446
 * Pretty printer for use within gdb.  This is not intended to be used
1447
 * outside of gdb.  This writes to the Warning() stream and immediately
1448
 * flushes the stream.
1449
 *
1450
 * Note that this function cannot be a template, since the compiler
1451
 * won't instantiate it.  Even if we explicitly instantiate.  (Odd?)
1452
 * So we implement twice.  We mark as __attribute__((used)) so that
1453
 * GCC emits code for it even though static analysis indicates it's
1454
 * never called.
1455
 *
1456
 * Tim's Note: I moved this into the node.h file because this allows gdb
1457
 * to find the symbol, and use it, which is the first standard this code needs
1458
 * to meet. A cleaner solution is welcomed.
1459
 */
1460
static void __attribute__((used)) debugPrintNode(const NodeTemplate<true>& n) {
1461
  Warning() << Node::setdepth(-1) << Node::dag(true)
1462
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1463
  Warning().flush();
1464
}
1465
static void __attribute__((used)) debugPrintNodeNoDag(const NodeTemplate<true>& n) {
1466
  Warning() << Node::setdepth(-1) << Node::dag(false)
1467
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1468
  Warning().flush();
1469
}
1470
static void __attribute__((used)) debugPrintRawNode(const NodeTemplate<true>& n) {
1471
  n.printAst(Warning(), 0);
1472
  Warning().flush();
1473
}
1474
1475
static void __attribute__((used)) debugPrintTNode(const NodeTemplate<false>& n) {
1476
  Warning() << Node::setdepth(-1) << Node::dag(true)
1477
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1478
  Warning().flush();
1479
}
1480
static void __attribute__((used)) debugPrintTNodeNoDag(const NodeTemplate<false>& n) {
1481
  Warning() << Node::setdepth(-1) << Node::dag(false)
1482
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1483
  Warning().flush();
1484
}
1485
static void __attribute__((used)) debugPrintRawTNode(const NodeTemplate<false>& n) {
1486
  n.printAst(Warning(), 0);
1487
  Warning().flush();
1488
}
1489
#endif /* CVC5_DEBUG */
1490
1491
}  // namespace cvc5
1492
1493
#endif /* CVC5__NODE_H */