GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node.h Lines: 300 363 82.6 %
Date: 2021-08-16 Branches: 801 3496 22.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
28479377383
  inline void assertTNodeNotExpired() const
228
  {
229
    if(!ref_count) {
230
11791272910
      Assert(d_nv->d_rc > 0) << "TNode pointing to an expired NodeValue";
231
    }
232
28479377383
  }
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
1016075470
 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
519032336
 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
4231198475
 bool isNull() const
319
 {
320
4231198475
   assertTNodeNotExpired();
321
4231198475
   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
3561878710
  bool operator==(const NodeTemplate<ref_count_1>& node) const {
331
3561878710
    assertTNodeNotExpired();
332
3561878710
    node.assertTNodeNotExpired();
333
3561878710
    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
137882122
  bool operator!=(const NodeTemplate<ref_count_1>& node) const {
343
137882122
    assertTNodeNotExpired();
344
137882122
    node.assertTNodeNotExpired();
345
137882122
    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
1252838470
  inline bool operator<(const NodeTemplate<ref_count_1>& node) const {
356
1252838470
    assertTNodeNotExpired();
357
1252838470
    node.assertTNodeNotExpired();
358
1252838470
    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
875226
  inline bool operator>(const NodeTemplate<ref_count_1>& node) const {
369
875226
    assertTNodeNotExpired();
370
875226
    node.assertTNodeNotExpired();
371
875226
    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
93
  inline bool operator<=(const NodeTemplate<ref_count_1>& node) const {
382
93
    assertTNodeNotExpired();
383
93
    node.assertTNodeNotExpired();
384
93
    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
53890
  inline bool operator>=(const NodeTemplate<ref_count_1>& node) const {
395
53890
    assertTNodeNotExpired();
396
53890
    node.assertTNodeNotExpired();
397
53890
    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
1225333085
  NodeTemplate operator[](int i) const {
406
1225333085
    assertTNodeNotExpired();
407
1225333085
    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
397372087
  inline bool isVar() const {
421
397372087
    assertTNodeNotExpired();
422
397372087
    return getMetaKind() == kind::metakind::VARIABLE;
423
  }
424
425
  /**
426
   * Returns true if this node represents a nullary operator
427
   */
428
3012
  inline bool isNullaryOp() const {
429
3012
    assertTNodeNotExpired();
430
3012
    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
44986662
  inline bool isClosure() const {
438
44986662
    assertTNodeNotExpired();
439
89967653
    return getKind() == kind::LAMBDA || getKind() == kind::FORALL
440
44577752
           || getKind() == kind::EXISTS || getKind() == kind::WITNESS
441
44576029
           || getKind() == kind::COMPREHENSION
442
89561887
           || getKind() == kind::MATCH_BIND_CASE;
443
  }
444
445
  /**
446
   * Returns the unique id of this node
447
   * @return the ud
448
   */
449
2449949660
  uint64_t getId() const
450
  {
451
2449949660
    assertTNodeNotExpired();
452
2449949660
    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
5868794422
  inline Kind getKind() const {
528
5868794422
    assertTNodeNotExpired();
529
5868794422
    return Kind(d_nv->d_kind);
530
  }
531
532
  /**
533
   * Returns the metakind of this node.
534
   * @return the metakind
535
   */
536
791589992
  inline kind::MetaKind getMetaKind() const {
537
791589992
    assertTNodeNotExpired();
538
791589992
    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
133632967
  inline iterator begin() {
686
133632967
    assertTNodeNotExpired();
687
133632967
    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
680223069
  inline iterator end() {
696
680223069
    assertTNodeNotExpired();
697
680223069
    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
101123136
  const_iterator begin() const
740
  {
741
101123136
    assertTNodeNotExpired();
742
101123136
    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
96323258
  const_iterator end() const
751
  {
752
96323258
    assertTNodeNotExpired();
753
96323258
    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
6195
  inline std::string toString() const {
816
6195
    assertTNodeNotExpired();
817
6195
    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
54172
  inline void toStream(
830
      std::ostream& out,
831
      int toDepth = -1,
832
      size_t dagThreshold = 1,
833
      OutputLanguage language = language::output::LANG_AUTO) const
834
  {
835
54172
    assertTNodeNotExpired();
836
54172
    d_nv->toStream(out, toDepth, dagThreshold, language);
837
54158
  }
838
839
  /**
840
   * IOStream manipulator to set the maximum depth of Nodes when
841
   * pretty-printing.  -1 means print to any depth.  E.g.:
842
   *
843
   *   // let a, b, c, and d be VARIABLEs
844
   *   Node n = nm->mkNode(OR, a, b, nm->mkNode(AND, c, nm->mkNode(NOT, d)))
845
   *   out << setdepth(3) << n;
846
   *
847
   * gives "(OR a b (AND c (NOT d)))", but
848
   *
849
   *   out << setdepth(1) << [same node as above]
850
   *
851
   * gives "(OR a b (...))"
852
   */
853
  typedef expr::ExprSetDepth setdepth;
854
855
  /**
856
   * IOStream manipulator to print expressions as DAGs (or not).
857
   */
858
  typedef expr::ExprDag dag;
859
860
  /**
861
   * IOStream manipulator to set the output language for Exprs.
862
   */
863
  typedef language::SetLanguage setlanguage;
864
865
  /**
866
   * Very basic pretty printer for Node.
867
   * @param out output stream to print to.
868
   * @param indent number of spaces to indent the formula by.
869
   */
870
  inline void printAst(std::ostream& out, int indent = 0) const;
871
872
  template <bool ref_count2>
873
  NodeTemplate<true> eqNode(const NodeTemplate<ref_count2>& right) const;
874
875
  NodeTemplate<true> notNode() const;
876
  NodeTemplate<true> negate() const;
877
  template <bool ref_count2>
878
  NodeTemplate<true> andNode(const NodeTemplate<ref_count2>& right) const;
879
  template <bool ref_count2>
880
  NodeTemplate<true> orNode(const NodeTemplate<ref_count2>& right) const;
881
  template <bool ref_count2, bool ref_count3>
882
  NodeTemplate<true> iteNode(const NodeTemplate<ref_count2>& thenpart,
883
                             const NodeTemplate<ref_count3>& elsepart) const;
884
  template <bool ref_count2>
885
  NodeTemplate<true> impNode(const NodeTemplate<ref_count2>& right) const;
886
  template <bool ref_count2>
887
  NodeTemplate<true> xorNode(const NodeTemplate<ref_count2>& right) const;
888
889
};/* class NodeTemplate<ref_count> */
890
891
/**
892
 * Serializes a given node to the given stream.
893
 *
894
 * @param out the output stream to use
895
 * @param n the node to output to the stream
896
 * @return the stream
897
 */
898
52830
inline std::ostream& operator<<(std::ostream& out, TNode n) {
899
105660
  n.toStream(out,
900
52830
             Node::setdepth::getDepth(out),
901
             Node::dag::getDag(out),
902
             Node::setlanguage::getLanguage(out));
903
52816
  return out;
904
}
905
906
/**
907
 * Serialize a vector of nodes to given stream.
908
 *
909
 * @param out the output stream to use
910
 * @param container the vector of nodes to output to the stream
911
 * @return the stream
912
 */
913
template <bool RC>
914
std::ostream& operator<<(std::ostream& out,
915
                         const std::vector<NodeTemplate<RC>>& container)
916
{
917
  container_to_stream(out, container);
918
  return out;
919
}
920
921
/**
922
 * Serialize a set of nodes to the given stream.
923
 *
924
 * @param out the output stream to use
925
 * @param container the set of nodes to output to the stream
926
 * @return the stream
927
 */
928
template <bool RC>
929
std::ostream& operator<<(std::ostream& out,
930
                         const std::set<NodeTemplate<RC>>& container)
931
{
932
  container_to_stream(out, container);
933
  return out;
934
}
935
936
/**
937
 * Serialize an unordered_set of nodes to the given stream.
938
 *
939
 * @param out the output stream to use
940
 * @param container the unordered_set of nodes to output to the stream
941
 * @return the stream
942
 */
943
template <bool RC, typename hash_function>
944
std::ostream& operator<<(
945
    std::ostream& out,
946
    const std::unordered_set<NodeTemplate<RC>, hash_function>& container)
947
{
948
  container_to_stream(out, container);
949
  return out;
950
}
951
952
/**
953
 * Serialize a map of nodes to the given stream.
954
 *
955
 * @param out the output stream to use
956
 * @param container the map of nodes to output to the stream
957
 * @return the stream
958
 */
959
template <bool RC, typename V>
960
std::ostream& operator<<(
961
    std::ostream& out,
962
    const std::map<NodeTemplate<RC>, V>& container)
963
{
964
  container_to_stream(out, container);
965
  return out;
966
}
967
968
/**
969
 * Serialize an unordered_map of nodes to the given stream.
970
 *
971
 * @param out the output stream to use
972
 * @param container the unordered_map of nodes to output to the stream
973
 * @return the stream
974
 */
975
template <bool RC, typename V, typename HF>
976
std::ostream& operator<<(
977
    std::ostream& out,
978
    const std::unordered_map<NodeTemplate<RC>, V, HF>& container)
979
{
980
  container_to_stream(out, container);
981
  return out;
982
}
983
984
}  // namespace cvc5
985
986
//#include "expr/attribute.h"
987
#include "expr/node_manager.h"
988
989
namespace cvc5 {
990
991
using TNodePairHashFunction =
992
    PairHashFunction<TNode, TNode, std::hash<TNode>, std::hash<TNode>>;
993
994
template <bool ref_count>
995
774010155
inline size_t NodeTemplate<ref_count>::getNumChildren() const {
996
774010155
  assertTNodeNotExpired();
997
774010155
  return d_nv->getNumChildren();
998
}
999
1000
template <bool ref_count>
1001
template <class T>
1002
582766846
inline const T& NodeTemplate<ref_count>::getConst() const {
1003
582766846
  assertTNodeNotExpired();
1004
582766846
  return d_nv->getConst<T>();
1005
}
1006
1007
template <bool ref_count>
1008
template <class AttrKind>
1009
199494739
inline typename AttrKind::value_type NodeTemplate<ref_count>::
1010
getAttribute(const AttrKind&) const {
1011
199494739
  Assert(NodeManager::currentNM() != NULL)
1012
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1013
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1014
1015
199494739
  assertTNodeNotExpired();
1016
1017
199494739
  return NodeManager::currentNM()->getAttribute(*this, AttrKind());
1018
}
1019
1020
template <bool ref_count>
1021
template <class AttrKind>
1022
162240599
inline bool NodeTemplate<ref_count>::
1023
hasAttribute(const AttrKind&) const {
1024
162240599
  Assert(NodeManager::currentNM() != NULL)
1025
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1026
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1027
1028
162240599
  assertTNodeNotExpired();
1029
1030
162240599
  return NodeManager::currentNM()->hasAttribute(*this, AttrKind());
1031
}
1032
1033
template <bool ref_count>
1034
template <class AttrKind>
1035
85094299
inline bool NodeTemplate<ref_count>::getAttribute(const AttrKind&,
1036
                                                  typename AttrKind::value_type& ret) const {
1037
85094299
  Assert(NodeManager::currentNM() != NULL)
1038
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1039
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1040
1041
85094299
  assertTNodeNotExpired();
1042
1043
85094299
  return NodeManager::currentNM()->getAttribute(*this, AttrKind(), ret);
1044
}
1045
1046
template <bool ref_count>
1047
template <class AttrKind>
1048
42927439
inline void NodeTemplate<ref_count>::
1049
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) {
1050
42927439
  Assert(NodeManager::currentNM() != NULL)
1051
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1052
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1053
1054
42927439
  assertTNodeNotExpired();
1055
1056
42927439
  NodeManager::currentNM()->setAttribute(*this, AttrKind(), value);
1057
42927439
}
1058
1059
template <bool ref_count>
1060
4235334
NodeTemplate<ref_count> NodeTemplate<ref_count>::s_null(&expr::NodeValue::null());
1061
1062
// FIXME: escape from type system convenient but is there a better
1063
// way?  Nodes conceptually don't change their expr values but of
1064
// course they do modify the refcount.  But it's nice to be able to
1065
// support node_iterators over const NodeValue*.  So.... hm.
1066
template <bool ref_count>
1067
2381336289
NodeTemplate<ref_count>::NodeTemplate(const expr::NodeValue* ev) :
1068
2381336289
  d_nv(const_cast<expr::NodeValue*> (ev)) {
1069
2381336289
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1070
  if(ref_count) {
1071
1455106661
    d_nv->inc();
1072
  } else {
1073
926229628
    Assert(d_nv->d_rc > 0 || d_nv == &expr::NodeValue::null())
1074
        << "TNode constructed from NodeValue with rc == 0";
1075
  }
1076
2381336289
}
1077
1078
// the code for these two following constructors ("conversion/copy
1079
// constructors") is identical, but we need both.  see comment in the
1080
// class.
1081
1082
template <bool ref_count>
1083
4783620582
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate<!ref_count>& e) {
1084
4783620582
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1085
4783620582
  d_nv = e.d_nv;
1086
  if(ref_count) {
1087
1596770039
    Assert(d_nv->d_rc > 0) << "Node constructed from TNode with rc == 0";
1088
1596770039
    d_nv->inc();
1089
  } else {
1090
    // shouldn't ever fail
1091
3186850543
    Assert(d_nv->d_rc > 0) << "TNode constructed from Node with rc == 0";
1092
  }
1093
4783620582
}
1094
1095
template <bool ref_count>
1096
19264769721
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate& e) {
1097
19264769721
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1098
19264769721
  d_nv = e.d_nv;
1099
  if(ref_count) {
1100
    // shouldn't ever fail
1101
10996877320
    Assert(d_nv->d_rc > 0) << "Node constructed from Node with rc == 0";
1102
10996877320
    d_nv->inc();
1103
  } else {
1104
8267892401
    Assert(d_nv->d_rc > 0) << "TNode constructed from TNode with rc == 0";
1105
  }
1106
19264769721
}
1107
1108
template <bool ref_count>
1109
27445800863
NodeTemplate<ref_count>::~NodeTemplate() {
1110
27445800863
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1111
  if(ref_count) {
1112
    // shouldn't ever fail
1113
14888978256
    Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1114
14888978256
    d_nv->dec();
1115
  }
1116
27445800863
}
1117
1118
template <bool ref_count>
1119
void NodeTemplate<ref_count>::assignNodeValue(expr::NodeValue* ev) {
1120
  d_nv = ev;
1121
  if(ref_count) {
1122
    d_nv->inc();
1123
  } else {
1124
    Assert(d_nv->d_rc > 0) << "TNode assigned to NodeValue with rc == 0";
1125
  }
1126
}
1127
1128
template <bool ref_count>
1129
1282065641
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1130
operator=(const NodeTemplate& e) {
1131
1282065641
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1132
1282065641
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1133
1282065641
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1134
    if(ref_count) {
1135
      // shouldn't ever fail
1136
671571791
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1137
671571791
      d_nv->dec();
1138
    }
1139
850030979
    d_nv = e.d_nv;
1140
    if(ref_count) {
1141
      // shouldn't ever fail
1142
671571791
      Assert(d_nv->d_rc > 0) << "Node assigned from Node with rc == 0";
1143
671571791
      d_nv->inc();
1144
    } else {
1145
178459188
      Assert(d_nv->d_rc > 0) << "TNode assigned from TNode with rc == 0";
1146
    }
1147
  }
1148
1282065641
  return *this;
1149
}
1150
1151
template <bool ref_count>
1152
97592554
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1153
operator=(const NodeTemplate<!ref_count>& e) {
1154
97592554
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1155
97592554
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1156
97592554
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1157
    if(ref_count) {
1158
      // shouldn't ever fail
1159
14754965
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1160
14754965
      d_nv->dec();
1161
    }
1162
95924033
    d_nv = e.d_nv;
1163
    if(ref_count) {
1164
14754965
      Assert(d_nv->d_rc > 0) << "Node assigned from TNode with rc == 0";
1165
14754965
      d_nv->inc();
1166
    } else {
1167
      // shouldn't ever happen
1168
81169068
      Assert(d_nv->d_rc > 0) << "TNode assigned from Node with rc == 0";
1169
    }
1170
  }
1171
97592554
  return *this;
1172
}
1173
1174
template <bool ref_count>
1175
template <bool ref_count2>
1176
NodeTemplate<true>
1177
31159099
NodeTemplate<ref_count>::eqNode(const NodeTemplate<ref_count2>& right) const {
1178
31159099
  assertTNodeNotExpired();
1179
31159099
  return NodeManager::currentNM()->mkNode(kind::EQUAL, *this, right);
1180
}
1181
1182
template <bool ref_count>
1183
31158817
NodeTemplate<true> NodeTemplate<ref_count>::notNode() const {
1184
31158817
  assertTNodeNotExpired();
1185
31158817
  return NodeManager::currentNM()->mkNode(kind::NOT, *this);
1186
}
1187
1188
template <bool ref_count>
1189
8639915
NodeTemplate<true> NodeTemplate<ref_count>::negate() const {
1190
8639915
  assertTNodeNotExpired();
1191
8639915
  return (getKind() == kind::NOT) ? NodeTemplate<true>(d_nv->getChild(0)) : NodeManager::currentNM()->mkNode(kind::NOT, *this);
1192
}
1193
1194
template <bool ref_count>
1195
template <bool ref_count2>
1196
NodeTemplate<true>
1197
144594
NodeTemplate<ref_count>::andNode(const NodeTemplate<ref_count2>& right) const {
1198
144594
  assertTNodeNotExpired();
1199
144594
  return NodeManager::currentNM()->mkNode(kind::AND, *this, right);
1200
}
1201
1202
template <bool ref_count>
1203
template <bool ref_count2>
1204
NodeTemplate<true>
1205
97551
NodeTemplate<ref_count>::orNode(const NodeTemplate<ref_count2>& right) const {
1206
97551
  assertTNodeNotExpired();
1207
97551
  return NodeManager::currentNM()->mkNode(kind::OR, *this, right);
1208
}
1209
1210
template <bool ref_count>
1211
template <bool ref_count2, bool ref_count3>
1212
NodeTemplate<true>
1213
240889
NodeTemplate<ref_count>::iteNode(const NodeTemplate<ref_count2>& thenpart,
1214
                                 const NodeTemplate<ref_count3>& elsepart) const {
1215
240889
  assertTNodeNotExpired();
1216
240889
  return NodeManager::currentNM()->mkNode(kind::ITE, *this, thenpart, elsepart);
1217
}
1218
1219
template <bool ref_count>
1220
template <bool ref_count2>
1221
NodeTemplate<true>
1222
100151
NodeTemplate<ref_count>::impNode(const NodeTemplate<ref_count2>& right) const {
1223
100151
  assertTNodeNotExpired();
1224
100151
  return NodeManager::currentNM()->mkNode(kind::IMPLIES, *this, right);
1225
}
1226
1227
template <bool ref_count>
1228
template <bool ref_count2>
1229
NodeTemplate<true>
1230
92
NodeTemplate<ref_count>::xorNode(const NodeTemplate<ref_count2>& right) const {
1231
92
  assertTNodeNotExpired();
1232
92
  return NodeManager::currentNM()->mkNode(kind::XOR, *this, right);
1233
}
1234
1235
template <bool ref_count>
1236
inline void
1237
NodeTemplate<ref_count>::printAst(std::ostream& out, int indent) const {
1238
  assertTNodeNotExpired();
1239
  d_nv->printAst(out, indent);
1240
}
1241
1242
/**
1243
 * Returns a node representing the operator of this expression.
1244
 * If this is an APPLY_UF, then the operator will be a functional term.
1245
 * Otherwise, it will be a node with kind BUILTIN.
1246
 */
1247
template <bool ref_count>
1248
29321890
NodeTemplate<true> NodeTemplate<ref_count>::getOperator() const
1249
{
1250
29321890
  Assert(NodeManager::currentNM() != NULL)
1251
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1252
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1253
1254
29321890
  assertTNodeNotExpired();
1255
1256
29321890
  kind::MetaKind mk = getMetaKind();
1257
29321890
  if (mk == kind::metakind::OPERATOR)
1258
  {
1259
    /* Returns a BUILTIN node. */
1260
5745760
    return NodeManager::currentNM()->operatorOf(getKind());
1261
  }
1262
23576130
  Assert(mk == kind::metakind::PARAMETERIZED);
1263
  /* The operator is the first child. */
1264
23576130
  return Node(d_nv->d_children[0]);
1265
}
1266
1267
/**
1268
 * Returns true if the node has an operator (i.e., it's not a variable
1269
 * or a constant).
1270
 */
1271
template <bool ref_count>
1272
13186312
inline bool NodeTemplate<ref_count>::hasOperator() const {
1273
13186312
  assertTNodeNotExpired();
1274
13186312
  return NodeManager::hasOperator(getKind());
1275
}
1276
1277
template <bool ref_count>
1278
516403794
TypeNode NodeTemplate<ref_count>::getType(bool check) const
1279
{
1280
516403794
  Assert(NodeManager::currentNM() != NULL)
1281
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1282
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1283
1284
516403794
  assertTNodeNotExpired();
1285
1286
516403795
  return NodeManager::currentNM()->getType(*this, check);
1287
}
1288
1289
template <bool ref_count>
1290
inline Node
1291
121178
NodeTemplate<ref_count>::substitute(TNode node, TNode replacement) const {
1292
121178
  if (node == *this) {
1293
6050
    return replacement;
1294
  }
1295
230256
  std::unordered_map<TNode, TNode> cache;
1296
115128
  return substitute(node, replacement, cache);
1297
}
1298
1299
template <bool ref_count>
1300
8802326
Node NodeTemplate<ref_count>::substitute(
1301
    TNode node,
1302
    TNode replacement,
1303
    std::unordered_map<TNode, TNode>& cache) const
1304
{
1305
8802326
  Assert(node != *this);
1306
1307
8802326
  if (getNumChildren() == 0 || node == replacement)
1308
  {
1309
2730749
    return *this;
1310
  }
1311
1312
  // in cache?
1313
6071577
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1314
      cache.find(*this);
1315
6071577
  if(i != cache.end()) {
1316
2419123
    return (*i).second;
1317
  }
1318
1319
  // otherwise compute
1320
7304908
  NodeBuilder nb(getKind());
1321
3652454
  if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1322
    // push the operator
1323
1025978
    if(getOperator() == node) {
1324
159
      nb << replacement;
1325
    } else {
1326
1025819
      nb << getOperator().substitute(node, replacement, cache);
1327
    }
1328
  }
1329
11505942
  for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1330
  {
1331
7853488
    if (*it == node)
1332
    {
1333
600218
      nb << replacement;
1334
    }
1335
    else
1336
    {
1337
7253270
      nb << (*it).substitute(node, replacement, cache);
1338
    }
1339
  }
1340
1341
  // put in cache
1342
7304908
  Node n = nb;
1343
3652454
  cache[*this] = n;
1344
3652454
  return n;
1345
}
1346
1347
template <bool ref_count>
1348
template <class Iterator1, class Iterator2>
1349
inline Node
1350
10062658
NodeTemplate<ref_count>::substitute(Iterator1 nodesBegin,
1351
                                    Iterator1 nodesEnd,
1352
                                    Iterator2 replacementsBegin,
1353
                                    Iterator2 replacementsEnd) const {
1354
20125316
  std::unordered_map<TNode, TNode> cache;
1355
  return substitute(nodesBegin, nodesEnd,
1356
20125316
                    replacementsBegin, replacementsEnd, cache);
1357
}
1358
1359
template <bool ref_count>
1360
template <class Iterator1, class Iterator2>
1361
51365649
Node NodeTemplate<ref_count>::substitute(
1362
    Iterator1 nodesBegin,
1363
    Iterator1 nodesEnd,
1364
    Iterator2 replacementsBegin,
1365
    Iterator2 replacementsEnd,
1366
    std::unordered_map<TNode, TNode>& cache) const
1367
{
1368
  // in cache?
1369
51365649
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1370
      cache.find(*this);
1371
51365649
  if(i != cache.end()) {
1372
16662190
    return (*i).second;
1373
  }
1374
1375
  // otherwise compute
1376
34703459
  Assert(std::distance(nodesBegin, nodesEnd)
1377
         == std::distance(replacementsBegin, replacementsEnd))
1378
      << "Substitution iterator ranges must be equal size";
1379
34703459
  Iterator1 j = std::find(nodesBegin, nodesEnd, TNode(*this));
1380
34703459
  if(j != nodesEnd) {
1381
3799436
    Iterator2 b = replacementsBegin;
1382
3799436
    std::advance(b, std::distance(nodesBegin, j));
1383
7598872
    Node n = *b;
1384
3799436
    cache[*this] = n;
1385
3799436
    return n;
1386
30904023
  } else if(getNumChildren() == 0) {
1387
15307154
    cache[*this] = *this;
1388
15307154
    return *this;
1389
  } else {
1390
31193738
    NodeBuilder nb(getKind());
1391
15596869
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1392
      // push the operator
1393
1181913
      nb << getOperator().substitute(nodesBegin, nodesEnd,
1394
                                     replacementsBegin, replacementsEnd,
1395
                                     cache);
1396
    }
1397
55717947
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1398
    {
1399
40121078
      nb << (*it).substitute(
1400
          nodesBegin, nodesEnd, replacementsBegin, replacementsEnd, cache);
1401
    }
1402
31193738
    Node n = nb;
1403
15596869
    cache[*this] = n;
1404
15596869
    return n;
1405
  }
1406
}
1407
1408
template <bool ref_count>
1409
template <class Iterator>
1410
inline Node
1411
106
NodeTemplate<ref_count>::substitute(Iterator substitutionsBegin,
1412
                                    Iterator substitutionsEnd) const {
1413
212
  std::unordered_map<TNode, TNode> cache;
1414
212
  return substitute(substitutionsBegin, substitutionsEnd, cache);
1415
}
1416
1417
template <bool ref_count>
1418
6
inline Node NodeTemplate<ref_count>::substitute(
1419
    std::unordered_map<TNode, TNode>& cache) const
1420
{
1421
  // Since no substitution is given (other than what may already be in the
1422
  // cache), we pass dummy iterators to conform to the main substitute method,
1423
  // giving the same value to substitutionsBegin and substitutionsEnd.
1424
6
  return substitute(cache.cend(), cache.cend(), cache);
1425
}
1426
1427
template <bool ref_count>
1428
template <class Iterator>
1429
582
Node NodeTemplate<ref_count>::substitute(
1430
    Iterator substitutionsBegin,
1431
    Iterator substitutionsEnd,
1432
    std::unordered_map<TNode, TNode>& cache) const
1433
{
1434
  // in cache?
1435
582
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1436
      cache.find(*this);
1437
582
  if(i != cache.end()) {
1438
56
    return (*i).second;
1439
  }
1440
1441
  // otherwise compute
1442
526
  Iterator j = find_if(
1443
      substitutionsBegin,
1444
      substitutionsEnd,
1445
5306
      [this](const auto& subst){ return subst.first == *this; });
1446
526
  if(j != substitutionsEnd) {
1447
314
    Node n = (*j).second;
1448
157
    cache[*this] = n;
1449
157
    return n;
1450
369
  } else if(getNumChildren() == 0) {
1451
199
    cache[*this] = *this;
1452
199
    return *this;
1453
  } else {
1454
340
    NodeBuilder nb(getKind());
1455
170
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1456
      // push the operator
1457
102
      nb << getOperator().substitute(substitutionsBegin, substitutionsEnd, cache);
1458
    }
1459
538
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1460
    {
1461
368
      nb << (*it).substitute(substitutionsBegin, substitutionsEnd, cache);
1462
    }
1463
340
    Node n = nb;
1464
170
    cache[*this] = n;
1465
170
    return n;
1466
  }
1467
}
1468
1469
#ifdef CVC5_DEBUG
1470
/**
1471
 * Pretty printer for use within gdb.  This is not intended to be used
1472
 * outside of gdb.  This writes to the Warning() stream and immediately
1473
 * flushes the stream.
1474
 *
1475
 * Note that this function cannot be a template, since the compiler
1476
 * won't instantiate it.  Even if we explicitly instantiate.  (Odd?)
1477
 * So we implement twice.  We mark as __attribute__((used)) so that
1478
 * GCC emits code for it even though static analysis indicates it's
1479
 * never called.
1480
 *
1481
 * Tim's Note: I moved this into the node.h file because this allows gdb
1482
 * to find the symbol, and use it, which is the first standard this code needs
1483
 * to meet. A cleaner solution is welcomed.
1484
 */
1485
static void __attribute__((used)) debugPrintNode(const NodeTemplate<true>& n) {
1486
  Warning() << Node::setdepth(-1)
1487
            << Node::dag(true)
1488
            << Node::setlanguage(language::output::LANG_AST)
1489
            << n << std::endl;
1490
  Warning().flush();
1491
}
1492
static void __attribute__((used)) debugPrintNodeNoDag(const NodeTemplate<true>& n) {
1493
  Warning() << Node::setdepth(-1)
1494
            << Node::dag(false)
1495
            << Node::setlanguage(language::output::LANG_AST)
1496
            << n << std::endl;
1497
  Warning().flush();
1498
}
1499
static void __attribute__((used)) debugPrintRawNode(const NodeTemplate<true>& n) {
1500
  n.printAst(Warning(), 0);
1501
  Warning().flush();
1502
}
1503
1504
static void __attribute__((used)) debugPrintTNode(const NodeTemplate<false>& n) {
1505
  Warning() << Node::setdepth(-1)
1506
            << Node::dag(true)
1507
            << Node::setlanguage(language::output::LANG_AST)
1508
            << n << std::endl;
1509
  Warning().flush();
1510
}
1511
static void __attribute__((used)) debugPrintTNodeNoDag(const NodeTemplate<false>& n) {
1512
  Warning() << Node::setdepth(-1)
1513
            << Node::dag(false)
1514
            << Node::setlanguage(language::output::LANG_AST)
1515
            << n << std::endl;
1516
  Warning().flush();
1517
}
1518
static void __attribute__((used)) debugPrintRawTNode(const NodeTemplate<false>& n) {
1519
  n.printAst(Warning(), 0);
1520
  Warning().flush();
1521
}
1522
#endif /* CVC5_DEBUG */
1523
1524
}  // namespace cvc5
1525
1526
#endif /* CVC5__NODE_H */