GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node.h Lines: 300 355 84.5 %
Date: 2021-09-16 Branches: 803 3496 23.0 %

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
30263093290
  inline void assertTNodeNotExpired() const
228
  {
229
    if(!ref_count) {
230
12301620752
      Assert(d_nv->d_rc > 0) << "TNode pointing to an expired NodeValue";
231
    }
232
30263093290
  }
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
1058805268
 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
552572731
 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
4412780148
 bool isNull() const
319
 {
320
4412780148
   assertTNodeNotExpired();
321
4412780148
   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
3676575886
  bool operator==(const NodeTemplate<ref_count_1>& node) const {
331
3676575886
    assertTNodeNotExpired();
332
3676575886
    node.assertTNodeNotExpired();
333
3676575886
    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
151502214
  bool operator!=(const NodeTemplate<ref_count_1>& node) const {
343
151502214
    assertTNodeNotExpired();
344
151502214
    node.assertTNodeNotExpired();
345
151502214
    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
1593680660
  inline bool operator<(const NodeTemplate<ref_count_1>& node) const {
356
1593680660
    assertTNodeNotExpired();
357
1593680660
    node.assertTNodeNotExpired();
358
1593680660
    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
947822
  inline bool operator>(const NodeTemplate<ref_count_1>& node) const {
369
947822
    assertTNodeNotExpired();
370
947822
    node.assertTNodeNotExpired();
371
947822
    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
91
  inline bool operator<=(const NodeTemplate<ref_count_1>& node) const {
382
91
    assertTNodeNotExpired();
383
91
    node.assertTNodeNotExpired();
384
91
    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
62389
  inline bool operator>=(const NodeTemplate<ref_count_1>& node) const {
395
62389
    assertTNodeNotExpired();
396
62389
    node.assertTNodeNotExpired();
397
62389
    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
1218181857
  NodeTemplate operator[](int i) const {
406
1218181857
    assertTNodeNotExpired();
407
1218181857
    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
424580104
  inline bool isVar() const {
421
424580104
    assertTNodeNotExpired();
422
424580104
    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
51704460
  inline bool isClosure() const {
438
51704460
    assertTNodeNotExpired();
439
103403064
    return getKind() == kind::LAMBDA || getKind() == kind::FORALL
440
51293485
           || getKind() == kind::EXISTS || getKind() == kind::WITNESS
441
51291798
           || getKind() == kind::COMPREHENSION
442
102995454
           || getKind() == kind::MATCH_BIND_CASE;
443
  }
444
445
  /**
446
   * Returns the unique id of this node
447
   * @return the ud
448
   */
449
2575962739
  uint64_t getId() const
450
  {
451
2575962739
    assertTNodeNotExpired();
452
2575962739
    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
6154003025
  inline Kind getKind() const {
528
6154003025
    assertTNodeNotExpired();
529
6154003025
    return Kind(d_nv->d_kind);
530
  }
531
532
  /**
533
   * Returns the metakind of this node.
534
   * @return the metakind
535
   */
536
835971205
  inline kind::MetaKind getMetaKind() const {
537
835971205
    assertTNodeNotExpired();
538
835971205
    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
162917183
  inline iterator begin() {
686
162917183
    assertTNodeNotExpired();
687
162917183
    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
728055160
  inline iterator end() {
696
728055160
    assertTNodeNotExpired();
697
728055160
    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
103842945
  const_iterator begin() const
740
  {
741
103842945
    assertTNodeNotExpired();
742
103842945
    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
97912606
  const_iterator end() const
751
  {
752
97912606
    assertTNodeNotExpired();
753
97912606
    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
6231
  inline std::string toString() const {
816
6231
    assertTNodeNotExpired();
817
6231
    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
59493
  inline void toStream(std::ostream& out,
830
                       int toDepth = -1,
831
                       size_t dagThreshold = 1,
832
                       Language language = Language::LANG_AUTO) const
833
  {
834
59493
    assertTNodeNotExpired();
835
59493
    d_nv->toStream(out, toDepth, dagThreshold, language);
836
59479
  }
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
58151
inline std::ostream& operator<<(std::ostream& out, TNode n) {
898
116302
  n.toStream(out,
899
58151
             Node::setdepth::getDepth(out),
900
             Node::dag::getDag(out),
901
             Node::setlanguage::getLanguage(out));
902
58137
  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
803498423
inline size_t NodeTemplate<ref_count>::getNumChildren() const {
995
803498423
  assertTNodeNotExpired();
996
803498423
  return d_nv->getNumChildren();
997
}
998
999
template <bool ref_count>
1000
template <class T>
1001
610264215
inline const T& NodeTemplate<ref_count>::getConst() const {
1002
610264215
  assertTNodeNotExpired();
1003
610264215
  return d_nv->getConst<T>();
1004
}
1005
1006
template <bool ref_count>
1007
template <class AttrKind>
1008
215395959
inline typename AttrKind::value_type NodeTemplate<ref_count>::
1009
getAttribute(const AttrKind&) const {
1010
215395959
  Assert(NodeManager::currentNM() != NULL)
1011
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1012
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1013
1014
215395959
  assertTNodeNotExpired();
1015
1016
215395959
  return NodeManager::currentNM()->getAttribute(*this, AttrKind());
1017
}
1018
1019
template <bool ref_count>
1020
template <class AttrKind>
1021
167607584
inline bool NodeTemplate<ref_count>::
1022
hasAttribute(const AttrKind&) const {
1023
167607584
  Assert(NodeManager::currentNM() != NULL)
1024
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1025
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1026
1027
167607584
  assertTNodeNotExpired();
1028
1029
167607584
  return NodeManager::currentNM()->hasAttribute(*this, AttrKind());
1030
}
1031
1032
template <bool ref_count>
1033
template <class AttrKind>
1034
88250172
inline bool NodeTemplate<ref_count>::getAttribute(const AttrKind&,
1035
                                                  typename AttrKind::value_type& ret) const {
1036
88250172
  Assert(NodeManager::currentNM() != NULL)
1037
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1038
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1039
1040
88250172
  assertTNodeNotExpired();
1041
1042
88250172
  return NodeManager::currentNM()->getAttribute(*this, AttrKind(), ret);
1043
}
1044
1045
template <bool ref_count>
1046
template <class AttrKind>
1047
44319658
inline void NodeTemplate<ref_count>::
1048
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) {
1049
44319658
  Assert(NodeManager::currentNM() != NULL)
1050
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1051
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1052
1053
44319658
  assertTNodeNotExpired();
1054
1055
44319658
  NodeManager::currentNM()->setAttribute(*this, AttrKind(), value);
1056
44319658
}
1057
1058
template <bool ref_count>
1059
4358280
NodeTemplate<ref_count> NodeTemplate<ref_count>::s_null(&expr::NodeValue::null());
1060
1061
// FIXME: escape from type system convenient but is there a better
1062
// way?  Nodes conceptually don't change their expr values but of
1063
// course they do modify the refcount.  But it's nice to be able to
1064
// support node_iterators over const NodeValue*.  So.... hm.
1065
template <bool ref_count>
1066
2412010912
NodeTemplate<ref_count>::NodeTemplate(const expr::NodeValue* ev) :
1067
2412010912
  d_nv(const_cast<expr::NodeValue*> (ev)) {
1068
2412010912
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1069
  if(ref_count) {
1070
1456502870
    d_nv->inc();
1071
  } else {
1072
955508042
    Assert(d_nv->d_rc > 0 || d_nv == &expr::NodeValue::null())
1073
        << "TNode constructed from NodeValue with rc == 0";
1074
  }
1075
2412010912
}
1076
1077
// the code for these two following constructors ("conversion/copy
1078
// constructors") is identical, but we need both.  see comment in the
1079
// class.
1080
1081
template <bool ref_count>
1082
5063881201
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate<!ref_count>& e) {
1083
5063881201
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1084
5063881201
  d_nv = e.d_nv;
1085
  if(ref_count) {
1086
1734256969
    Assert(d_nv->d_rc > 0) << "Node constructed from TNode with rc == 0";
1087
1734256969
    d_nv->inc();
1088
  } else {
1089
    // shouldn't ever fail
1090
3329624232
    Assert(d_nv->d_rc > 0) << "TNode constructed from Node with rc == 0";
1091
  }
1092
5063881201
}
1093
1094
template <bool ref_count>
1095
20250258472
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate& e) {
1096
20250258472
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1097
20250258472
  d_nv = e.d_nv;
1098
  if(ref_count) {
1099
    // shouldn't ever fail
1100
11610123927
    Assert(d_nv->d_rc > 0) << "Node constructed from Node with rc == 0";
1101
11610123927
    d_nv->inc();
1102
  } else {
1103
8640134545
    Assert(d_nv->d_rc > 0) << "TNode constructed from TNode with rc == 0";
1104
  }
1105
20250258472
}
1106
1107
template <bool ref_count>
1108
28784082740
NodeTemplate<ref_count>::~NodeTemplate() {
1109
28784082740
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1110
  if(ref_count) {
1111
    // shouldn't ever fail
1112
15677872373
    Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1113
15677872373
    d_nv->dec();
1114
  }
1115
28784082740
}
1116
1117
template <bool ref_count>
1118
void NodeTemplate<ref_count>::assignNodeValue(expr::NodeValue* ev) {
1119
  d_nv = ev;
1120
  if(ref_count) {
1121
    d_nv->inc();
1122
  } else {
1123
    Assert(d_nv->d_rc > 0) << "TNode assigned to NodeValue with rc == 0";
1124
  }
1125
}
1126
1127
template <bool ref_count>
1128
1382484579
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1129
operator=(const NodeTemplate& e) {
1130
1382484579
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1131
1382484579
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1132
1382484579
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1133
    if(ref_count) {
1134
      // shouldn't ever fail
1135
690969810
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1136
690969810
      d_nv->dec();
1137
    }
1138
911743189
    d_nv = e.d_nv;
1139
    if(ref_count) {
1140
      // shouldn't ever fail
1141
690969810
      Assert(d_nv->d_rc > 0) << "Node assigned from Node with rc == 0";
1142
690969810
      d_nv->inc();
1143
    } else {
1144
220773379
      Assert(d_nv->d_rc > 0) << "TNode assigned from TNode with rc == 0";
1145
    }
1146
  }
1147
1382484579
  return *this;
1148
}
1149
1150
template <bool ref_count>
1151
97903447
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1152
operator=(const NodeTemplate<!ref_count>& e) {
1153
97903447
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1154
97903447
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1155
97903447
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1156
    if(ref_count) {
1157
      // shouldn't ever fail
1158
15985708
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1159
15985708
      d_nv->dec();
1160
    }
1161
94257742
    d_nv = e.d_nv;
1162
    if(ref_count) {
1163
15985708
      Assert(d_nv->d_rc > 0) << "Node assigned from TNode with rc == 0";
1164
15985708
      d_nv->inc();
1165
    } else {
1166
      // shouldn't ever happen
1167
78272034
      Assert(d_nv->d_rc > 0) << "TNode assigned from Node with rc == 0";
1168
    }
1169
  }
1170
97903447
  return *this;
1171
}
1172
1173
template <bool ref_count>
1174
template <bool ref_count2>
1175
NodeTemplate<true>
1176
32054054
NodeTemplate<ref_count>::eqNode(const NodeTemplate<ref_count2>& right) const {
1177
32054054
  assertTNodeNotExpired();
1178
32054054
  return NodeManager::currentNM()->mkNode(kind::EQUAL, *this, right);
1179
}
1180
1181
template <bool ref_count>
1182
29465519
NodeTemplate<true> NodeTemplate<ref_count>::notNode() const {
1183
29465519
  assertTNodeNotExpired();
1184
29465519
  return NodeManager::currentNM()->mkNode(kind::NOT, *this);
1185
}
1186
1187
template <bool ref_count>
1188
8721330
NodeTemplate<true> NodeTemplate<ref_count>::negate() const {
1189
8721330
  assertTNodeNotExpired();
1190
8721330
  return (getKind() == kind::NOT) ? NodeTemplate<true>(d_nv->getChild(0)) : NodeManager::currentNM()->mkNode(kind::NOT, *this);
1191
}
1192
1193
template <bool ref_count>
1194
template <bool ref_count2>
1195
NodeTemplate<true>
1196
112804
NodeTemplate<ref_count>::andNode(const NodeTemplate<ref_count2>& right) const {
1197
112804
  assertTNodeNotExpired();
1198
112804
  return NodeManager::currentNM()->mkNode(kind::AND, *this, right);
1199
}
1200
1201
template <bool ref_count>
1202
template <bool ref_count2>
1203
NodeTemplate<true>
1204
99034
NodeTemplate<ref_count>::orNode(const NodeTemplate<ref_count2>& right) const {
1205
99034
  assertTNodeNotExpired();
1206
99034
  return NodeManager::currentNM()->mkNode(kind::OR, *this, right);
1207
}
1208
1209
template <bool ref_count>
1210
template <bool ref_count2, bool ref_count3>
1211
NodeTemplate<true>
1212
264962
NodeTemplate<ref_count>::iteNode(const NodeTemplate<ref_count2>& thenpart,
1213
                                 const NodeTemplate<ref_count3>& elsepart) const {
1214
264962
  assertTNodeNotExpired();
1215
264962
  return NodeManager::currentNM()->mkNode(kind::ITE, *this, thenpart, elsepart);
1216
}
1217
1218
template <bool ref_count>
1219
template <bool ref_count2>
1220
NodeTemplate<true>
1221
118539
NodeTemplate<ref_count>::impNode(const NodeTemplate<ref_count2>& right) const {
1222
118539
  assertTNodeNotExpired();
1223
118539
  return NodeManager::currentNM()->mkNode(kind::IMPLIES, *this, right);
1224
}
1225
1226
template <bool ref_count>
1227
template <bool ref_count2>
1228
NodeTemplate<true>
1229
92
NodeTemplate<ref_count>::xorNode(const NodeTemplate<ref_count2>& right) const {
1230
92
  assertTNodeNotExpired();
1231
92
  return NodeManager::currentNM()->mkNode(kind::XOR, *this, right);
1232
}
1233
1234
template <bool ref_count>
1235
inline void
1236
NodeTemplate<ref_count>::printAst(std::ostream& out, int indent) const {
1237
  assertTNodeNotExpired();
1238
  d_nv->printAst(out, indent);
1239
}
1240
1241
/**
1242
 * Returns a node representing the operator of this expression.
1243
 * If this is an APPLY_UF, then the operator will be a functional term.
1244
 * Otherwise, it will be a node with kind BUILTIN.
1245
 */
1246
template <bool ref_count>
1247
30644524
NodeTemplate<true> NodeTemplate<ref_count>::getOperator() const
1248
{
1249
30644524
  Assert(NodeManager::currentNM() != NULL)
1250
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1251
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1252
1253
30644524
  assertTNodeNotExpired();
1254
1255
30644524
  kind::MetaKind mk = getMetaKind();
1256
30644524
  if (mk == kind::metakind::OPERATOR)
1257
  {
1258
    /* Returns a BUILTIN node. */
1259
6222956
    return NodeManager::currentNM()->operatorOf(getKind());
1260
  }
1261
24421568
  Assert(mk == kind::metakind::PARAMETERIZED);
1262
  /* The operator is the first child. */
1263
24421568
  return Node(d_nv->d_children[0]);
1264
}
1265
1266
/**
1267
 * Returns true if the node has an operator (i.e., it's not a variable
1268
 * or a constant).
1269
 */
1270
template <bool ref_count>
1271
13779997
inline bool NodeTemplate<ref_count>::hasOperator() const {
1272
13779997
  assertTNodeNotExpired();
1273
13779997
  return NodeManager::hasOperator(getKind());
1274
}
1275
1276
template <bool ref_count>
1277
525390945
TypeNode NodeTemplate<ref_count>::getType(bool check) const
1278
{
1279
525390945
  Assert(NodeManager::currentNM() != NULL)
1280
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1281
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1282
1283
525390945
  assertTNodeNotExpired();
1284
1285
525390948
  return NodeManager::currentNM()->getType(*this, check);
1286
}
1287
1288
template <bool ref_count>
1289
inline Node
1290
66071
NodeTemplate<ref_count>::substitute(TNode node, TNode replacement) const {
1291
66071
  if (node == *this) {
1292
3979
    return replacement;
1293
  }
1294
124184
  std::unordered_map<TNode, TNode> cache;
1295
62092
  return substitute(node, replacement, cache);
1296
}
1297
1298
template <bool ref_count>
1299
5732221
Node NodeTemplate<ref_count>::substitute(
1300
    TNode node,
1301
    TNode replacement,
1302
    std::unordered_map<TNode, TNode>& cache) const
1303
{
1304
5732221
  Assert(node != *this);
1305
1306
5732221
  if (getNumChildren() == 0 || node == replacement)
1307
  {
1308
1576363
    return *this;
1309
  }
1310
1311
  // in cache?
1312
4155858
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1313
      cache.find(*this);
1314
4155858
  if(i != cache.end()) {
1315
1795975
    return (*i).second;
1316
  }
1317
1318
  // otherwise compute
1319
4719766
  NodeBuilder nb(getKind());
1320
2359883
  if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1321
    // push the operator
1322
853202
    if(getOperator() == node) {
1323
158
      nb << replacement;
1324
    } else {
1325
853044
      nb << getOperator().substitute(node, replacement, cache);
1326
    }
1327
  }
1328
7329824
  for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1329
  {
1330
4969941
    if (*it == node)
1331
    {
1332
570790
      nb << replacement;
1333
    }
1334
    else
1335
    {
1336
4399151
      nb << (*it).substitute(node, replacement, cache);
1337
    }
1338
  }
1339
1340
  // put in cache
1341
4719766
  Node n = nb;
1342
2359883
  cache[*this] = n;
1343
2359883
  return n;
1344
}
1345
1346
template <bool ref_count>
1347
template <class Iterator1, class Iterator2>
1348
inline Node
1349
9925937
NodeTemplate<ref_count>::substitute(Iterator1 nodesBegin,
1350
                                    Iterator1 nodesEnd,
1351
                                    Iterator2 replacementsBegin,
1352
                                    Iterator2 replacementsEnd) const {
1353
19851874
  std::unordered_map<TNode, TNode> cache;
1354
  return substitute(nodesBegin, nodesEnd,
1355
19851874
                    replacementsBegin, replacementsEnd, cache);
1356
}
1357
1358
template <bool ref_count>
1359
template <class Iterator1, class Iterator2>
1360
45442295
Node NodeTemplate<ref_count>::substitute(
1361
    Iterator1 nodesBegin,
1362
    Iterator1 nodesEnd,
1363
    Iterator2 replacementsBegin,
1364
    Iterator2 replacementsEnd,
1365
    std::unordered_map<TNode, TNode>& cache) const
1366
{
1367
  // in cache?
1368
45442295
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1369
      cache.find(*this);
1370
45442295
  if(i != cache.end()) {
1371
13151729
    return (*i).second;
1372
  }
1373
1374
  // otherwise compute
1375
32290566
  Assert(std::distance(nodesBegin, nodesEnd)
1376
         == std::distance(replacementsBegin, replacementsEnd))
1377
      << "Substitution iterator ranges must be equal size";
1378
32290566
  Iterator1 j = std::find(nodesBegin, nodesEnd, TNode(*this));
1379
32290566
  if(j != nodesEnd) {
1380
3153168
    Iterator2 b = replacementsBegin;
1381
3153168
    std::advance(b, std::distance(nodesBegin, j));
1382
6306336
    Node n = *b;
1383
3153168
    cache[*this] = n;
1384
3153168
    return n;
1385
29137398
  } else if(getNumChildren() == 0) {
1386
15109734
    cache[*this] = *this;
1387
15109734
    return *this;
1388
  } else {
1389
28055328
    NodeBuilder nb(getKind());
1390
14027664
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1391
      // push the operator
1392
1080354
      nb << getOperator().substitute(nodesBegin, nodesEnd,
1393
                                     replacementsBegin, replacementsEnd,
1394
                                     cache);
1395
    }
1396
48463668
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1397
    {
1398
34436004
      nb << (*it).substitute(
1399
          nodesBegin, nodesEnd, replacementsBegin, replacementsEnd, cache);
1400
    }
1401
28055328
    Node n = nb;
1402
14027664
    cache[*this] = n;
1403
14027664
    return n;
1404
  }
1405
}
1406
1407
template <bool ref_count>
1408
template <class Iterator>
1409
inline Node
1410
66136
NodeTemplate<ref_count>::substitute(Iterator substitutionsBegin,
1411
                                    Iterator substitutionsEnd) const {
1412
132272
  std::unordered_map<TNode, TNode> cache;
1413
132272
  return substitute(substitutionsBegin, substitutionsEnd, cache);
1414
}
1415
1416
template <bool ref_count>
1417
6
inline Node NodeTemplate<ref_count>::substitute(
1418
    std::unordered_map<TNode, TNode>& cache) const
1419
{
1420
  // Since no substitution is given (other than what may already be in the
1421
  // cache), we pass dummy iterators to conform to the main substitute method,
1422
  // giving the same value to substitutionsBegin and substitutionsEnd.
1423
6
  return substitute(cache.cend(), cache.cend(), cache);
1424
}
1425
1426
template <bool ref_count>
1427
template <class Iterator>
1428
129935
Node NodeTemplate<ref_count>::substitute(
1429
    Iterator substitutionsBegin,
1430
    Iterator substitutionsEnd,
1431
    std::unordered_map<TNode, TNode>& cache) const
1432
{
1433
  // in cache?
1434
129935
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1435
      cache.find(*this);
1436
129935
  if(i != cache.end()) {
1437
1030
    return (*i).second;
1438
  }
1439
1440
  // otherwise compute
1441
128905
  Iterator j = find_if(
1442
      substitutionsBegin,
1443
      substitutionsEnd,
1444
2582633
      [this](const auto& subst){ return subst.first == *this; });
1445
128905
  if(j != substitutionsEnd) {
1446
124244
    Node n = (*j).second;
1447
62122
    cache[*this] = n;
1448
62122
    return n;
1449
66783
  } else if(getNumChildren() == 0) {
1450
36615
    cache[*this] = *this;
1451
36615
    return *this;
1452
  } else {
1453
60336
    NodeBuilder nb(getKind());
1454
30168
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1455
      // push the operator
1456
102
      nb << getOperator().substitute(substitutionsBegin, substitutionsEnd, cache);
1457
    }
1458
93859
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1459
    {
1460
63691
      nb << (*it).substitute(substitutionsBegin, substitutionsEnd, cache);
1461
    }
1462
60336
    Node n = nb;
1463
30168
    cache[*this] = n;
1464
30168
    return n;
1465
  }
1466
}
1467
1468
#ifdef CVC5_DEBUG
1469
/**
1470
 * Pretty printer for use within gdb.  This is not intended to be used
1471
 * outside of gdb.  This writes to the Warning() stream and immediately
1472
 * flushes the stream.
1473
 *
1474
 * Note that this function cannot be a template, since the compiler
1475
 * won't instantiate it.  Even if we explicitly instantiate.  (Odd?)
1476
 * So we implement twice.  We mark as __attribute__((used)) so that
1477
 * GCC emits code for it even though static analysis indicates it's
1478
 * never called.
1479
 *
1480
 * Tim's Note: I moved this into the node.h file because this allows gdb
1481
 * to find the symbol, and use it, which is the first standard this code needs
1482
 * to meet. A cleaner solution is welcomed.
1483
 */
1484
static void __attribute__((used)) debugPrintNode(const NodeTemplate<true>& n) {
1485
  Warning() << Node::setdepth(-1) << Node::dag(true)
1486
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1487
  Warning().flush();
1488
}
1489
static void __attribute__((used)) debugPrintNodeNoDag(const NodeTemplate<true>& n) {
1490
  Warning() << Node::setdepth(-1) << Node::dag(false)
1491
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1492
  Warning().flush();
1493
}
1494
static void __attribute__((used)) debugPrintRawNode(const NodeTemplate<true>& n) {
1495
  n.printAst(Warning(), 0);
1496
  Warning().flush();
1497
}
1498
1499
static void __attribute__((used)) debugPrintTNode(const NodeTemplate<false>& n) {
1500
  Warning() << Node::setdepth(-1) << Node::dag(true)
1501
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1502
  Warning().flush();
1503
}
1504
static void __attribute__((used)) debugPrintTNodeNoDag(const NodeTemplate<false>& n) {
1505
  Warning() << Node::setdepth(-1) << Node::dag(false)
1506
            << Node::setlanguage(Language::LANG_AST) << n << std::endl;
1507
  Warning().flush();
1508
}
1509
static void __attribute__((used)) debugPrintRawTNode(const NodeTemplate<false>& n) {
1510
  n.printAst(Warning(), 0);
1511
  Warning().flush();
1512
}
1513
#endif /* CVC5_DEBUG */
1514
1515
}  // namespace cvc5
1516
1517
#endif /* CVC5__NODE_H */