GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node.h Lines: 294 357 82.4 %
Date: 2021-05-21 Branches: 794 3500 22.7 %

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/CVC4/CVC4/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
25359599245
  inline void assertTNodeNotExpired() const
228
  {
229
    if(!ref_count) {
230
10094778327
      Assert(d_nv->d_rc > 0) << "TNode pointing to an expired NodeValue";
231
    }
232
25359599245
  }
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
908487008
 NodeTemplate() : d_nv(&expr::NodeValue::null()) {}
266
267
 /**
268
  * Conversion between nodes that are reference-counted and those that are
269
  * not.
270
  * @param node the node to make copy of
271
  */
272
 NodeTemplate(const NodeTemplate<!ref_count>& node);
273
274
 /**
275
  * Copy constructor.  Note that GCC does NOT recognize an instantiation of
276
  * the above template as a copy constructor and problems ensue.  So we
277
  * provide an explicit one here.
278
  * @param node the node to make copy of
279
  */
280
 NodeTemplate(const NodeTemplate& node);
281
282
 /**
283
  * Assignment operator for nodes, copies the relevant information from node
284
  * to this node.
285
  * @param node the node to copy
286
  * @return reference to this node
287
  */
288
 NodeTemplate& operator=(const NodeTemplate& node);
289
290
 /**
291
  * Assignment operator for nodes, copies the relevant information from node
292
  * to this node.
293
  * @param node the node to copy
294
  * @return reference to this node
295
  */
296
 NodeTemplate& operator=(const NodeTemplate<!ref_count>& node);
297
298
 /**
299
  * Destructor. If ref_count is true it will decrement the reference count
300
  * and, if zero, collect the NodeValue.
301
  */
302
 ~NodeTemplate();
303
304
 /**
305
  * Return the null node.
306
  * @return the null node
307
  */
308
429250576
 static NodeTemplate null() { return s_null; }
309
310
 /**
311
  * Returns true if this expression is a null expression.
312
  * @return true if null
313
  */
314
3776847022
 bool isNull() const
315
 {
316
3776847022
   assertTNodeNotExpired();
317
3776847022
   return d_nv == &expr::NodeValue::null();
318
 }
319
320
  /**
321
   * Structural comparison operator for expressions.
322
   * @param node the node to compare to
323
   * @return true if expressions are equal, false otherwise
324
   */
325
  template <bool ref_count_1>
326
3025302098
  bool operator==(const NodeTemplate<ref_count_1>& node) const {
327
3025302098
    assertTNodeNotExpired();
328
3025302098
    node.assertTNodeNotExpired();
329
3025302098
    return d_nv == node.d_nv;
330
  }
331
332
  /**
333
   * Structural comparison operator for expressions.
334
   * @param node the node to compare to
335
   * @return false if expressions are equal, true otherwise
336
   */
337
  template <bool ref_count_1>
338
127331093
  bool operator!=(const NodeTemplate<ref_count_1>& node) const {
339
127331093
    assertTNodeNotExpired();
340
127331093
    node.assertTNodeNotExpired();
341
127331093
    return d_nv != node.d_nv;
342
  }
343
344
  /**
345
   * We compare by expression ids so, keeping things deterministic and having
346
   * that subexpressions have to be smaller than the enclosing expressions.
347
   * @param node the node to compare to
348
   * @return true if this expression is smaller
349
   */
350
  template <bool ref_count_1>
351
1255443389
  inline bool operator<(const NodeTemplate<ref_count_1>& node) const {
352
1255443389
    assertTNodeNotExpired();
353
1255443389
    node.assertTNodeNotExpired();
354
1255443389
    return d_nv->d_id < node.d_nv->d_id;
355
  }
356
357
  /**
358
   * We compare by expression ids so, keeping things deterministic and having
359
   * that subexpressions have to be smaller than the enclosing expressions.
360
   * @param node the node to compare to
361
   * @return true if this expression is greater
362
   */
363
  template <bool ref_count_1>
364
626413
  inline bool operator>(const NodeTemplate<ref_count_1>& node) const {
365
626413
    assertTNodeNotExpired();
366
626413
    node.assertTNodeNotExpired();
367
626413
    return d_nv->d_id > node.d_nv->d_id;
368
  }
369
370
  /**
371
   * We compare by expression ids so, keeping things deterministic and having
372
   * that subexpressions have to be smaller than the enclosing expressions.
373
   * @param node the node to compare to
374
   * @return true if this expression is smaller than or equal to
375
   */
376
  template <bool ref_count_1>
377
88
  inline bool operator<=(const NodeTemplate<ref_count_1>& node) const {
378
88
    assertTNodeNotExpired();
379
88
    node.assertTNodeNotExpired();
380
88
    return d_nv->d_id <= node.d_nv->d_id;
381
  }
382
383
  /**
384
   * We compare by expression ids so, keeping things deterministic and having
385
   * that subexpressions have to be smaller than the enclosing expressions.
386
   * @param node the node to compare to
387
   * @return true if this expression is greater than or equal to
388
   */
389
  template <bool ref_count_1>
390
39750
  inline bool operator>=(const NodeTemplate<ref_count_1>& node) const {
391
39750
    assertTNodeNotExpired();
392
39750
    node.assertTNodeNotExpired();
393
39750
    return d_nv->d_id >= node.d_nv->d_id;
394
  }
395
396
  /**
397
   * Returns the i-th child of this node.
398
   * @param i the index of the child
399
   * @return the node representing the i-th child
400
   */
401
1117300004
  NodeTemplate operator[](int i) const {
402
1117300004
    assertTNodeNotExpired();
403
1117300004
    return NodeTemplate(d_nv->getChild(i));
404
  }
405
406
  /**
407
   * Returns true if this node represents a constant
408
   * @return true if const
409
   */
410
  bool isConst() const;
411
412
  /**
413
   * Returns true if this node represents a variable
414
   * @return true if variable
415
   */
416
344656528
  inline bool isVar() const {
417
344656528
    assertTNodeNotExpired();
418
344656528
    return getMetaKind() == kind::metakind::VARIABLE;
419
  }
420
421
  /**
422
   * Returns true if this node represents a nullary operator
423
   */
424
3471
  inline bool isNullaryOp() const {
425
3471
    assertTNodeNotExpired();
426
3471
    return getMetaKind() == kind::metakind::NULLARY_OPERATOR;
427
  }
428
429
  /**
430
   * Returns true if this node represents a closure, that is an expression
431
   * that binds variables.
432
   */
433
41061282
  inline bool isClosure() const {
434
41061282
    assertTNodeNotExpired();
435
82116305
    return getKind() == kind::LAMBDA || getKind() == kind::FORALL
436
40652471
           || getKind() == kind::EXISTS || getKind() == kind::WITNESS
437
40650562
           || getKind() == kind::COMPREHENSION
438
81711032
           || getKind() == kind::MATCH_BIND_CASE;
439
  }
440
441
  /**
442
   * Returns the unique id of this node
443
   * @return the ud
444
   */
445
2148258687
  uint64_t getId() const
446
  {
447
2148258687
    assertTNodeNotExpired();
448
2148258687
    return d_nv->getId();
449
  }
450
451
  /**
452
   * Returns a node representing the operator of this expression.
453
   * If this is an APPLY_UF, then the operator will be a functional term.
454
   * Otherwise, it will be a node with kind BUILTIN.
455
   */
456
  NodeTemplate<true> getOperator() const;
457
458
  /**
459
   * Returns true if the node has an operator (i.e., it's not a
460
   * variable or a constant).
461
   */
462
  inline bool hasOperator() const;
463
464
  /**
465
   * Get the type for the node and optionally do type checking.
466
   *
467
   * Initial type computation will be near-constant time if
468
   * type checking is not requested. Results are memoized, so that
469
   * subsequent calls to getType() without type checking will be
470
   * constant time.
471
   *
472
   * Initial type checking is linear in the size of the expression.
473
   * Again, the results are memoized, so that subsequent calls to
474
   * getType(), with or without type checking, will be constant
475
   * time.
476
   *
477
   * NOTE: A TypeCheckingException can be thrown even when type
478
   * checking is not requested. getType() will always return a
479
   * valid and correct type and, thus, an exception will be thrown
480
   * when no valid or correct type can be computed (e.g., if the
481
   * arguments to a bit-vector operation aren't bit-vectors). When
482
   * type checking is not requested, getType() will do the minimum
483
   * amount of checking required to return a valid result.
484
   *
485
   * @param check whether we should check the type as we compute it
486
   * (default: false)
487
   */
488
  TypeNode getType(bool check = false) const;
489
490
  /**
491
   * Substitution of Nodes.
492
   */
493
  Node substitute(TNode node, TNode replacement) const;
494
495
  /**
496
   * Simultaneous substitution of Nodes.  Elements in the Iterator1
497
   * range will be replaced by their corresponding element in the
498
   * Iterator2 range.  Both ranges should have the same size.
499
   */
500
  template <class Iterator1, class Iterator2>
501
  Node substitute(Iterator1 nodesBegin,
502
                  Iterator1 nodesEnd,
503
                  Iterator2 replacementsBegin,
504
                  Iterator2 replacementsEnd) const;
505
506
  /**
507
   * Simultaneous substitution of Nodes.  Iterators should be over
508
   * pairs (x,y) for the rewrites [x->y].
509
   */
510
  template <class Iterator>
511
  Node substitute(Iterator substitutionsBegin,
512
                  Iterator substitutionsEnd) const;
513
514
  /**
515
   * Simultaneous substitution of Nodes in cache.
516
   */
517
  Node substitute(std::unordered_map<TNode, TNode>& cache) const;
518
519
  /**
520
   * Returns the kind of this node.
521
   * @return the kind
522
   */
523
5248363758
  inline Kind getKind() const {
524
5248363758
    assertTNodeNotExpired();
525
5248363758
    return Kind(d_nv->d_kind);
526
  }
527
528
  /**
529
   * Returns the metakind of this node.
530
   * @return the metakind
531
   */
532
707500437
  inline kind::MetaKind getMetaKind() const {
533
707500437
    assertTNodeNotExpired();
534
707500437
    return kind::metaKindOf(getKind());
535
  }
536
537
  /**
538
   * Returns the number of children this node has.
539
   * @return the number of children
540
   */
541
  inline size_t getNumChildren() const;
542
543
  /**
544
   * If this is a CONST_* Node, extract the constant from it.
545
   */
546
  template <class T>
547
  inline const T& getConst() const;
548
549
  /**
550
   * Returns the reference count of this node.
551
   * @return the refcount
552
   */
553
  unsigned getRefCount() const {
554
    return d_nv->getRefCount();
555
  }
556
557
  /**
558
   * Returns the value of the given attribute that this has been attached.
559
   * @param attKind the kind of the attribute
560
   * @return the value of the attribute
561
   */
562
  template <class AttrKind>
563
  inline typename AttrKind::value_type getAttribute(const AttrKind& attKind) const;
564
565
  // Note that there are two, distinct hasAttribute() declarations for
566
  // a reason (rather than using a pointer-valued argument with a
567
  // default value): they permit more optimized code in the underlying
568
  // hasAttribute() implementations.
569
570
  /**
571
   * Returns true if this node has been associated an attribute of given kind.
572
   * Additionaly, if a pointer to the value_kind is give, and the attribute
573
   * value has been set for this node, it will be returned.
574
   * @param attKind the kind of the attribute
575
   * @return true if this node has the requested attribute
576
   */
577
  template <class AttrKind>
578
  inline bool hasAttribute(const AttrKind& attKind) const;
579
580
  /**
581
   * Returns true if this node has been associated an attribute of given kind.
582
   * Additionaly, if a pointer to the value_kind is give, and the attribute
583
   * value has been set for this node, it will be returned.
584
   * @param attKind the kind of the attribute
585
   * @param value where to store the value if it exists
586
   * @return true if this node has the requested attribute
587
   */
588
  template <class AttrKind>
589
  inline bool getAttribute(const AttrKind& attKind,
590
                           typename AttrKind::value_type& value) const;
591
592
  /**
593
   * Sets the given attribute of this node to the given value.
594
   * @param attKind the kind of the atribute
595
   * @param value the value to set the attribute to
596
   */
597
  template <class AttrKind>
598
  inline void setAttribute(const AttrKind& attKind,
599
                           const typename AttrKind::value_type& value);
600
601
  /** Iterator allowing for scanning through the children. */
602
  typedef typename expr::NodeValue::iterator< NodeTemplate<ref_count> > iterator;
603
  /** Constant iterator allowing for scanning through the children. */
604
  typedef typename expr::NodeValue::iterator< NodeTemplate<ref_count> > const_iterator;
605
606
18
  class kinded_iterator {
607
    friend class NodeTemplate<ref_count>;
608
609
    NodeTemplate<ref_count> d_node;
610
    ssize_t d_child;
611
612
8
    kinded_iterator(TNode node, ssize_t child) :
613
      d_node(node),
614
8
      d_child(child) {
615
8
    }
616
617
    // These are factories to serve as clients to Node::begin<K>() and
618
    // Node::end<K>().
619
4
    static kinded_iterator begin(TNode n, Kind k) {
620
4
      return kinded_iterator(n, n.getKind() == k ? 0 : -2);
621
    }
622
4
    static kinded_iterator end(TNode n, Kind k) {
623
4
      return kinded_iterator(n, n.getKind() == k ? n.getNumChildren() : -1);
624
    }
625
626
  public:
627
    typedef NodeTemplate<ref_count> value_type;
628
    typedef std::ptrdiff_t difference_type;
629
    typedef NodeTemplate<ref_count>* pointer;
630
    typedef NodeTemplate<ref_count>& reference;
631
632
    kinded_iterator() :
633
      d_node(NodeTemplate<ref_count>::null()),
634
      d_child(-2) {
635
    }
636
637
8
    kinded_iterator(const kinded_iterator& i) :
638
      d_node(i.d_node),
639
8
      d_child(i.d_child) {
640
8
    }
641
642
8
    NodeTemplate<ref_count> operator*() {
643
8
      return d_child < 0 ? d_node : d_node[d_child];
644
    }
645
646
4
    bool operator==(const kinded_iterator& i) {
647
4
      return d_node == i.d_node && d_child == i.d_child;
648
    }
649
650
    bool operator!=(const kinded_iterator& i) {
651
      return !(*this == i);
652
    }
653
654
8
    kinded_iterator& operator++() {
655
8
      if(d_child != -1) {
656
8
        ++d_child;
657
      }
658
8
      return *this;
659
    }
660
661
8
    kinded_iterator operator++(int) {
662
8
      kinded_iterator i = *this;
663
8
      ++*this;
664
8
      return i;
665
    }
666
  };/* class NodeTemplate<ref_count>::kinded_iterator */
667
668
  typedef kinded_iterator const_kinded_iterator;
669
670
  /**
671
   * Returns the iterator pointing to the first child.
672
   * @return the iterator
673
   */
674
107429833
  inline iterator begin() {
675
107429833
    assertTNodeNotExpired();
676
107429833
    return d_nv->begin< NodeTemplate<ref_count> >();
677
  }
678
679
  /**
680
   * Returns the iterator pointing to the end of the children (one beyond the
681
   * last one).
682
   * @return the end of the children iterator.
683
   */
684
593964069
  inline iterator end() {
685
593964069
    assertTNodeNotExpired();
686
593964069
    return d_nv->end< NodeTemplate<ref_count> >();
687
  }
688
689
  /**
690
   * Returns the iterator pointing to the first child, if the node's
691
   * kind is the same as the parameter, otherwise returns the iterator
692
   * pointing to the node itself.  This is useful if you want to
693
   * pretend to iterate over a "unary" PLUS, for instance, since unary
694
   * PLUSes don't exist---begin(PLUS) will give an iterator over the
695
   * children if the node's a PLUS node, otherwise give an iterator
696
   * over the node itself, as if it were a unary PLUS.
697
   * @param kind the kind to match
698
   * @return the kinded_iterator iterating over this Node (if its kind
699
   * is not the passed kind) or its children
700
   */
701
4
  inline kinded_iterator begin(Kind kind) {
702
4
    assertTNodeNotExpired();
703
4
    return kinded_iterator::begin(*this, kind);
704
  }
705
706
  /**
707
   * Returns the iterator pointing to the end of the children (one
708
   * beyond the last one), if the node's kind is the same as the
709
   * parameter, otherwise returns the iterator pointing to the
710
   * one-of-the-node-itself.  This is useful if you want to pretend to
711
   * iterate over a "unary" PLUS, for instance, since unary PLUSes
712
   * don't exist---begin(PLUS) will give an iterator over the children
713
   * if the node's a PLUS node, otherwise give an iterator over the
714
   * node itself, as if it were a unary PLUS.
715
   * @param kind the kind to match
716
   * @return the kinded_iterator pointing off-the-end of this Node (if
717
   * its kind is not the passed kind) or off-the-end of its children
718
   */
719
4
  inline kinded_iterator end(Kind kind) {
720
4
    assertTNodeNotExpired();
721
4
    return kinded_iterator::end(*this, kind);
722
  }
723
724
  /**
725
   * Returns the const_iterator pointing to the first child.
726
   * @return the const_iterator
727
   */
728
96371264
  inline const_iterator begin() const {
729
96371264
    assertTNodeNotExpired();
730
96371264
    return d_nv->begin< NodeTemplate<ref_count> >();
731
  }
732
733
  /**
734
   * Returns the const_iterator pointing to the end of the children (one
735
   * beyond the last one.
736
   * @return the end of the children const_iterator.
737
   */
738
94804300
  inline const_iterator end() const {
739
94804300
    assertTNodeNotExpired();
740
94804300
    return d_nv->end< NodeTemplate<ref_count> >();
741
  }
742
743
  /**
744
   * Returns the iterator pointing to the first child, if the node's
745
   * kind is the same as the parameter, otherwise returns the iterator
746
   * pointing to the node itself.  This is useful if you want to
747
   * pretend to iterate over a "unary" PLUS, for instance, since unary
748
   * PLUSes don't exist---begin(PLUS) will give an iterator over the
749
   * children if the node's a PLUS node, otherwise give an iterator
750
   * over the node itself, as if it were a unary PLUS.
751
   * @param kind the kind to match
752
   * @return the kinded_iterator iterating over this Node (if its kind
753
   * is not the passed kind) or its children
754
   */
755
  inline const_kinded_iterator begin(Kind kind) const {
756
    assertTNodeNotExpired();
757
    return const_kinded_iterator::begin(*this, kind);
758
  }
759
760
  /**
761
   * Returns the iterator pointing to the end of the children (one
762
   * beyond the last one), if the node's kind is the same as the
763
   * parameter, otherwise returns the iterator pointing to the
764
   * one-of-the-node-itself.  This is useful if you want to pretend to
765
   * iterate over a "unary" PLUS, for instance, since unary PLUSes
766
   * don't exist---begin(PLUS) will give an iterator over the children
767
   * if the node's a PLUS node, otherwise give an iterator over the
768
   * node itself, as if it were a unary PLUS.
769
   * @param kind the kind to match
770
   * @return the kinded_iterator pointing off-the-end of this Node (if
771
   * its kind is not the passed kind) or off-the-end of its children
772
   */
773
  inline const_kinded_iterator end(Kind kind) const {
774
    assertTNodeNotExpired();
775
    return const_kinded_iterator::end(*this, kind);
776
  }
777
778
  /**
779
   * Converts this node into a string representation.
780
   * @return the string representation of this node.
781
   */
782
5771
  inline std::string toString() const {
783
5771
    assertTNodeNotExpired();
784
5771
    return d_nv->toString();
785
  }
786
787
  /**
788
   * Converts this node into a string representation and sends it to the
789
   * given stream
790
   *
791
   * @param out the stream to serialize this node to
792
   * @param toDepth the depth to which to print this expression, or -1 to
793
   * print it fully
794
   * @param language the language in which to output
795
   */
796
60378
  inline void toStream(
797
      std::ostream& out,
798
      int toDepth = -1,
799
      size_t dagThreshold = 1,
800
      OutputLanguage language = language::output::LANG_AUTO) const
801
  {
802
60378
    assertTNodeNotExpired();
803
60378
    d_nv->toStream(out, toDepth, dagThreshold, language);
804
60364
  }
805
806
  /**
807
   * IOStream manipulator to set the maximum depth of Nodes when
808
   * pretty-printing.  -1 means print to any depth.  E.g.:
809
   *
810
   *   // let a, b, c, and d be VARIABLEs
811
   *   Node n = nm->mkNode(OR, a, b, nm->mkNode(AND, c, nm->mkNode(NOT, d)))
812
   *   out << setdepth(3) << n;
813
   *
814
   * gives "(OR a b (AND c (NOT d)))", but
815
   *
816
   *   out << setdepth(1) << [same node as above]
817
   *
818
   * gives "(OR a b (...))"
819
   */
820
  typedef expr::ExprSetDepth setdepth;
821
822
  /**
823
   * IOStream manipulator to print expressions as DAGs (or not).
824
   */
825
  typedef expr::ExprDag dag;
826
827
  /**
828
   * IOStream manipulator to set the output language for Exprs.
829
   */
830
  typedef language::SetLanguage setlanguage;
831
832
  /**
833
   * Very basic pretty printer for Node.
834
   * @param out output stream to print to.
835
   * @param indent number of spaces to indent the formula by.
836
   */
837
  inline void printAst(std::ostream& out, int indent = 0) const;
838
839
  template <bool ref_count2>
840
  NodeTemplate<true> eqNode(const NodeTemplate<ref_count2>& right) const;
841
842
  NodeTemplate<true> notNode() const;
843
  NodeTemplate<true> negate() const;
844
  template <bool ref_count2>
845
  NodeTemplate<true> andNode(const NodeTemplate<ref_count2>& right) const;
846
  template <bool ref_count2>
847
  NodeTemplate<true> orNode(const NodeTemplate<ref_count2>& right) const;
848
  template <bool ref_count2, bool ref_count3>
849
  NodeTemplate<true> iteNode(const NodeTemplate<ref_count2>& thenpart,
850
                             const NodeTemplate<ref_count3>& elsepart) const;
851
  template <bool ref_count2>
852
  NodeTemplate<true> impNode(const NodeTemplate<ref_count2>& right) const;
853
  template <bool ref_count2>
854
  NodeTemplate<true> xorNode(const NodeTemplate<ref_count2>& right) const;
855
856
};/* class NodeTemplate<ref_count> */
857
858
/**
859
 * Serializes a given node to the given stream.
860
 *
861
 * @param out the output stream to use
862
 * @param n the node to output to the stream
863
 * @return the stream
864
 */
865
54102
inline std::ostream& operator<<(std::ostream& out, TNode n) {
866
108204
  n.toStream(out,
867
54102
             Node::setdepth::getDepth(out),
868
             Node::dag::getDag(out),
869
             Node::setlanguage::getLanguage(out));
870
54088
  return out;
871
}
872
873
/**
874
 * Serialize a vector of nodes to given stream.
875
 *
876
 * @param out the output stream to use
877
 * @param container the vector of nodes to output to the stream
878
 * @return the stream
879
 */
880
template <bool RC>
881
std::ostream& operator<<(std::ostream& out,
882
                         const std::vector<NodeTemplate<RC>>& container)
883
{
884
  container_to_stream(out, container);
885
  return out;
886
}
887
888
/**
889
 * Serialize a set of nodes to the given stream.
890
 *
891
 * @param out the output stream to use
892
 * @param container the set of nodes to output to the stream
893
 * @return the stream
894
 */
895
template <bool RC>
896
std::ostream& operator<<(std::ostream& out,
897
                         const std::set<NodeTemplate<RC>>& container)
898
{
899
  container_to_stream(out, container);
900
  return out;
901
}
902
903
/**
904
 * Serialize an unordered_set of nodes to the given stream.
905
 *
906
 * @param out the output stream to use
907
 * @param container the unordered_set of nodes to output to the stream
908
 * @return the stream
909
 */
910
template <bool RC, typename hash_function>
911
std::ostream& operator<<(
912
    std::ostream& out,
913
    const std::unordered_set<NodeTemplate<RC>, hash_function>& container)
914
{
915
  container_to_stream(out, container);
916
  return out;
917
}
918
919
/**
920
 * Serialize a map of nodes to the given stream.
921
 *
922
 * @param out the output stream to use
923
 * @param container the map of nodes to output to the stream
924
 * @return the stream
925
 */
926
template <bool RC, typename V>
927
std::ostream& operator<<(
928
    std::ostream& out,
929
    const std::map<NodeTemplate<RC>, V>& container)
930
{
931
  container_to_stream(out, container);
932
  return out;
933
}
934
935
/**
936
 * Serialize an unordered_map of nodes to the given stream.
937
 *
938
 * @param out the output stream to use
939
 * @param container the unordered_map of nodes to output to the stream
940
 * @return the stream
941
 */
942
template <bool RC, typename V, typename HF>
943
std::ostream& operator<<(
944
    std::ostream& out,
945
    const std::unordered_map<NodeTemplate<RC>, V, HF>& container)
946
{
947
  container_to_stream(out, container);
948
  return out;
949
}
950
951
}  // namespace cvc5
952
953
//#include "expr/attribute.h"
954
#include "expr/node_manager.h"
955
956
namespace cvc5 {
957
958
using TNodePairHashFunction =
959
    PairHashFunction<TNode, TNode, std::hash<TNode>, std::hash<TNode>>;
960
961
template <bool ref_count>
962
709435327
inline size_t NodeTemplate<ref_count>::getNumChildren() const {
963
709435327
  assertTNodeNotExpired();
964
709435327
  return d_nv->getNumChildren();
965
}
966
967
template <bool ref_count>
968
template <class T>
969
518900147
inline const T& NodeTemplate<ref_count>::getConst() const {
970
518900147
  assertTNodeNotExpired();
971
518900147
  return d_nv->getConst<T>();
972
}
973
974
template <bool ref_count>
975
template <class AttrKind>
976
123282449
inline typename AttrKind::value_type NodeTemplate<ref_count>::
977
getAttribute(const AttrKind&) const {
978
123282449
  Assert(NodeManager::currentNM() != NULL)
979
      << "There is no current cvc5::NodeManager associated to this thread.\n"
980
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
981
982
123282449
  assertTNodeNotExpired();
983
984
123282449
  return NodeManager::currentNM()->getAttribute(*this, AttrKind());
985
}
986
987
template <bool ref_count>
988
template <class AttrKind>
989
152335067
inline bool NodeTemplate<ref_count>::
990
hasAttribute(const AttrKind&) const {
991
152335067
  Assert(NodeManager::currentNM() != NULL)
992
      << "There is no current cvc5::NodeManager associated to this thread.\n"
993
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
994
995
152335067
  assertTNodeNotExpired();
996
997
152335067
  return NodeManager::currentNM()->hasAttribute(*this, AttrKind());
998
}
999
1000
template <bool ref_count>
1001
template <class AttrKind>
1002
77631520
inline bool NodeTemplate<ref_count>::getAttribute(const AttrKind&,
1003
                                                  typename AttrKind::value_type& ret) const {
1004
77631520
  Assert(NodeManager::currentNM() != NULL)
1005
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1006
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1007
1008
77631520
  assertTNodeNotExpired();
1009
1010
77631520
  return NodeManager::currentNM()->getAttribute(*this, AttrKind(), ret);
1011
}
1012
1013
template <bool ref_count>
1014
template <class AttrKind>
1015
38062135
inline void NodeTemplate<ref_count>::
1016
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) {
1017
38062135
  Assert(NodeManager::currentNM() != NULL)
1018
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1019
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1020
1021
38062135
  assertTNodeNotExpired();
1022
1023
38062135
  NodeManager::currentNM()->setAttribute(*this, AttrKind(), value);
1024
38062135
}
1025
1026
template <bool ref_count>
1027
3791023
NodeTemplate<ref_count> NodeTemplate<ref_count>::s_null(&expr::NodeValue::null());
1028
1029
// FIXME: escape from type system convenient but is there a better
1030
// way?  Nodes conceptually don't change their expr values but of
1031
// course they do modify the refcount.  But it's nice to be able to
1032
// support node_iterators over const NodeValue*.  So.... hm.
1033
template <bool ref_count>
1034
2179317628
NodeTemplate<ref_count>::NodeTemplate(const expr::NodeValue* ev) :
1035
2179317628
  d_nv(const_cast<expr::NodeValue*> (ev)) {
1036
2179317628
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1037
  if(ref_count) {
1038
1380570979
    d_nv->inc();
1039
  } else {
1040
798746649
    Assert(d_nv->d_rc > 0 || d_nv == &expr::NodeValue::null())
1041
        << "TNode constructed from NodeValue with rc == 0";
1042
  }
1043
2179317628
}
1044
1045
// the code for these two following constructors ("conversion/copy
1046
// constructors") is identical, but we need both.  see comment in the
1047
// class.
1048
1049
template <bool ref_count>
1050
4527632470
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate<!ref_count>& e) {
1051
4527632470
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1052
4527632470
  d_nv = e.d_nv;
1053
  if(ref_count) {
1054
1547632481
    Assert(d_nv->d_rc > 0) << "Node constructed from TNode with rc == 0";
1055
1547632481
    d_nv->inc();
1056
  } else {
1057
    // shouldn't ever fail
1058
2979999989
    Assert(d_nv->d_rc > 0) << "TNode constructed from Node with rc == 0";
1059
  }
1060
4527632470
}
1061
1062
template <bool ref_count>
1063
17133156676
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate& e) {
1064
17133156676
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1065
17133156676
  d_nv = e.d_nv;
1066
  if(ref_count) {
1067
    // shouldn't ever fail
1068
9906419779
    Assert(d_nv->d_rc > 0) << "Node constructed from Node with rc == 0";
1069
9906419779
    d_nv->inc();
1070
  } else {
1071
7226736897
    Assert(d_nv->d_rc > 0) << "TNode constructed from TNode with rc == 0";
1072
  }
1073
17133156676
}
1074
1075
template <bool ref_count>
1076
24748592625
NodeTemplate<ref_count>::~NodeTemplate() {
1077
24748592625
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1078
  if(ref_count) {
1079
    // shouldn't ever fail
1080
13607306965
    Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1081
13607306965
    d_nv->dec();
1082
  }
1083
24748592625
}
1084
1085
template <bool ref_count>
1086
void NodeTemplate<ref_count>::assignNodeValue(expr::NodeValue* ev) {
1087
  d_nv = ev;
1088
  if(ref_count) {
1089
    d_nv->inc();
1090
  } else {
1091
    Assert(d_nv->d_rc > 0) << "TNode assigned to NodeValue with rc == 0";
1092
  }
1093
}
1094
1095
template <bool ref_count>
1096
1095431787
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1097
operator=(const NodeTemplate& e) {
1098
1095431787
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1099
1095431787
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1100
1095431787
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1101
    if(ref_count) {
1102
      // shouldn't ever fail
1103
616570231
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1104
616570231
      d_nv->dec();
1105
    }
1106
707369255
    d_nv = e.d_nv;
1107
    if(ref_count) {
1108
      // shouldn't ever fail
1109
616570231
      Assert(d_nv->d_rc > 0) << "Node assigned from Node with rc == 0";
1110
616570231
      d_nv->inc();
1111
    } else {
1112
90799024
      Assert(d_nv->d_rc > 0) << "TNode assigned from TNode with rc == 0";
1113
    }
1114
  }
1115
1095431787
  return *this;
1116
}
1117
1118
template <bool ref_count>
1119
83951500
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1120
operator=(const NodeTemplate<!ref_count>& e) {
1121
83951500
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1122
83951500
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1123
83951500
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1124
    if(ref_count) {
1125
      // shouldn't ever fail
1126
9738511
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1127
9738511
      d_nv->dec();
1128
    }
1129
82117615
    d_nv = e.d_nv;
1130
    if(ref_count) {
1131
9738511
      Assert(d_nv->d_rc > 0) << "Node assigned from TNode with rc == 0";
1132
9738511
      d_nv->inc();
1133
    } else {
1134
      // shouldn't ever happen
1135
72379104
      Assert(d_nv->d_rc > 0) << "TNode assigned from Node with rc == 0";
1136
    }
1137
  }
1138
83951500
  return *this;
1139
}
1140
1141
template <bool ref_count>
1142
template <bool ref_count2>
1143
NodeTemplate<true>
1144
26313550
NodeTemplate<ref_count>::eqNode(const NodeTemplate<ref_count2>& right) const {
1145
26313550
  assertTNodeNotExpired();
1146
26313550
  return NodeManager::currentNM()->mkNode(kind::EQUAL, *this, right);
1147
}
1148
1149
template <bool ref_count>
1150
39548540
NodeTemplate<true> NodeTemplate<ref_count>::notNode() const {
1151
39548540
  assertTNodeNotExpired();
1152
39548540
  return NodeManager::currentNM()->mkNode(kind::NOT, *this);
1153
}
1154
1155
template <bool ref_count>
1156
7654388
NodeTemplate<true> NodeTemplate<ref_count>::negate() const {
1157
7654388
  assertTNodeNotExpired();
1158
7654388
  return (getKind() == kind::NOT) ? NodeTemplate<true>(d_nv->getChild(0)) : NodeManager::currentNM()->mkNode(kind::NOT, *this);
1159
}
1160
1161
template <bool ref_count>
1162
template <bool ref_count2>
1163
NodeTemplate<true>
1164
149287
NodeTemplate<ref_count>::andNode(const NodeTemplate<ref_count2>& right) const {
1165
149287
  assertTNodeNotExpired();
1166
149287
  return NodeManager::currentNM()->mkNode(kind::AND, *this, right);
1167
}
1168
1169
template <bool ref_count>
1170
template <bool ref_count2>
1171
NodeTemplate<true>
1172
88546
NodeTemplate<ref_count>::orNode(const NodeTemplate<ref_count2>& right) const {
1173
88546
  assertTNodeNotExpired();
1174
88546
  return NodeManager::currentNM()->mkNode(kind::OR, *this, right);
1175
}
1176
1177
template <bool ref_count>
1178
template <bool ref_count2, bool ref_count3>
1179
NodeTemplate<true>
1180
262136
NodeTemplate<ref_count>::iteNode(const NodeTemplate<ref_count2>& thenpart,
1181
                                 const NodeTemplate<ref_count3>& elsepart) const {
1182
262136
  assertTNodeNotExpired();
1183
262136
  return NodeManager::currentNM()->mkNode(kind::ITE, *this, thenpart, elsepart);
1184
}
1185
1186
template <bool ref_count>
1187
template <bool ref_count2>
1188
NodeTemplate<true>
1189
88311
NodeTemplate<ref_count>::impNode(const NodeTemplate<ref_count2>& right) const {
1190
88311
  assertTNodeNotExpired();
1191
88311
  return NodeManager::currentNM()->mkNode(kind::IMPLIES, *this, right);
1192
}
1193
1194
template <bool ref_count>
1195
template <bool ref_count2>
1196
NodeTemplate<true>
1197
92
NodeTemplate<ref_count>::xorNode(const NodeTemplate<ref_count2>& right) const {
1198
92
  assertTNodeNotExpired();
1199
92
  return NodeManager::currentNM()->mkNode(kind::XOR, *this, right);
1200
}
1201
1202
template <bool ref_count>
1203
inline void
1204
NodeTemplate<ref_count>::printAst(std::ostream& out, int indent) const {
1205
  assertTNodeNotExpired();
1206
  d_nv->printAst(out, indent);
1207
}
1208
1209
/**
1210
 * Returns a node representing the operator of this expression.
1211
 * If this is an APPLY_UF, then the operator will be a functional term.
1212
 * Otherwise, it will be a node with kind BUILTIN.
1213
 */
1214
template <bool ref_count>
1215
29812212
NodeTemplate<true> NodeTemplate<ref_count>::getOperator() const
1216
{
1217
29812212
  Assert(NodeManager::currentNM() != NULL)
1218
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1219
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1220
1221
29812212
  assertTNodeNotExpired();
1222
1223
29812212
  kind::MetaKind mk = getMetaKind();
1224
29812212
  if (mk == kind::metakind::OPERATOR)
1225
  {
1226
    /* Returns a BUILTIN node. */
1227
5290834
    return NodeManager::currentNM()->operatorOf(getKind());
1228
  }
1229
24521378
  Assert(mk == kind::metakind::PARAMETERIZED);
1230
  /* The operator is the first child. */
1231
24521378
  return Node(d_nv->d_children[0]);
1232
}
1233
1234
/**
1235
 * Returns true if the node has an operator (i.e., it's not a variable
1236
 * or a constant).
1237
 */
1238
template <bool ref_count>
1239
14566395
inline bool NodeTemplate<ref_count>::hasOperator() const {
1240
14566395
  assertTNodeNotExpired();
1241
14566395
  return NodeManager::hasOperator(getKind());
1242
}
1243
1244
template <bool ref_count>
1245
463956417
TypeNode NodeTemplate<ref_count>::getType(bool check) const
1246
{
1247
463956417
  Assert(NodeManager::currentNM() != NULL)
1248
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1249
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1250
1251
463956417
  assertTNodeNotExpired();
1252
1253
463956418
  return NodeManager::currentNM()->getType(*this, check);
1254
}
1255
1256
template <bool ref_count>
1257
inline Node
1258
109256
NodeTemplate<ref_count>::substitute(TNode node, TNode replacement) const {
1259
109256
  if (node == *this) {
1260
3968
    return replacement;
1261
  }
1262
210576
  std::unordered_map<TNode, TNode> cache;
1263
105288
  return substitute(node, replacement, cache);
1264
}
1265
1266
template <bool ref_count>
1267
10134064
Node NodeTemplate<ref_count>::substitute(
1268
    TNode node,
1269
    TNode replacement,
1270
    std::unordered_map<TNode, TNode>& cache) const
1271
{
1272
10134064
  Assert(node != *this);
1273
1274
10134064
  if (getNumChildren() == 0 || node == replacement)
1275
  {
1276
3191870
    return *this;
1277
  }
1278
1279
  // in cache?
1280
6942194
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1281
      cache.find(*this);
1282
6942194
  if(i != cache.end()) {
1283
2784128
    return (*i).second;
1284
  }
1285
1286
  // otherwise compute
1287
8316132
  NodeBuilder nb(getKind());
1288
4158066
  if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1289
    // push the operator
1290
1178733
    if(getOperator() == node) {
1291
155
      nb << replacement;
1292
    } else {
1293
1178578
      nb << getOperator().substitute(node, replacement, cache);
1294
    }
1295
  }
1296
13222557
  for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1297
  {
1298
9064491
    if (*it == node)
1299
    {
1300
602819
      nb << replacement;
1301
    }
1302
    else
1303
    {
1304
8461672
      nb << (*it).substitute(node, replacement, cache);
1305
    }
1306
  }
1307
1308
  // put in cache
1309
8316132
  Node n = nb;
1310
4158066
  cache[*this] = n;
1311
4158066
  return n;
1312
}
1313
1314
template <bool ref_count>
1315
template <class Iterator1, class Iterator2>
1316
inline Node
1317
9315636
NodeTemplate<ref_count>::substitute(Iterator1 nodesBegin,
1318
                                    Iterator1 nodesEnd,
1319
                                    Iterator2 replacementsBegin,
1320
                                    Iterator2 replacementsEnd) const {
1321
18631272
  std::unordered_map<TNode, TNode> cache;
1322
  return substitute(nodesBegin, nodesEnd,
1323
18631272
                    replacementsBegin, replacementsEnd, cache);
1324
}
1325
1326
template <bool ref_count>
1327
template <class Iterator1, class Iterator2>
1328
42763585
Node NodeTemplate<ref_count>::substitute(
1329
    Iterator1 nodesBegin,
1330
    Iterator1 nodesEnd,
1331
    Iterator2 replacementsBegin,
1332
    Iterator2 replacementsEnd,
1333
    std::unordered_map<TNode, TNode>& cache) const
1334
{
1335
  // in cache?
1336
42763585
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1337
      cache.find(*this);
1338
42763585
  if(i != cache.end()) {
1339
11746904
    return (*i).second;
1340
  }
1341
1342
  // otherwise compute
1343
31016681
  Assert(std::distance(nodesBegin, nodesEnd)
1344
         == std::distance(replacementsBegin, replacementsEnd))
1345
      << "Substitution iterator ranges must be equal size";
1346
31016681
  Iterator1 j = std::find(nodesBegin, nodesEnd, TNode(*this));
1347
31016681
  if(j != nodesEnd) {
1348
2864072
    Iterator2 b = replacementsBegin;
1349
2864072
    std::advance(b, std::distance(nodesBegin, j));
1350
5728144
    Node n = *b;
1351
2864072
    cache[*this] = n;
1352
2864072
    return n;
1353
28152609
  } else if(getNumChildren() == 0) {
1354
14794370
    cache[*this] = *this;
1355
14794370
    return *this;
1356
  } else {
1357
26716478
    NodeBuilder nb(getKind());
1358
13358239
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1359
      // push the operator
1360
1604399
      nb << getOperator().substitute(nodesBegin, nodesEnd,
1361
                                     replacementsBegin, replacementsEnd,
1362
                                     cache);
1363
    }
1364
45201789
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1365
    {
1366
31843550
      nb << (*it).substitute(
1367
          nodesBegin, nodesEnd, replacementsBegin, replacementsEnd, cache);
1368
    }
1369
26716478
    Node n = nb;
1370
13358239
    cache[*this] = n;
1371
13358239
    return n;
1372
  }
1373
}
1374
1375
template <bool ref_count>
1376
template <class Iterator>
1377
inline Node
1378
101
NodeTemplate<ref_count>::substitute(Iterator substitutionsBegin,
1379
                                    Iterator substitutionsEnd) const {
1380
202
  std::unordered_map<TNode, TNode> cache;
1381
202
  return substitute(substitutionsBegin, substitutionsEnd, cache);
1382
}
1383
1384
template <bool ref_count>
1385
4
inline Node NodeTemplate<ref_count>::substitute(
1386
    std::unordered_map<TNode, TNode>& cache) const
1387
{
1388
  // Since no substitution is given (other than what may already be in the
1389
  // cache), we pass dummy iterators to conform to the main substitute method,
1390
  // giving the same value to substitutionsBegin and substitutionsEnd.
1391
4
  return substitute(cache.cend(), cache.cend(), cache);
1392
}
1393
1394
template <bool ref_count>
1395
template <class Iterator>
1396
535
Node NodeTemplate<ref_count>::substitute(
1397
    Iterator substitutionsBegin,
1398
    Iterator substitutionsEnd,
1399
    std::unordered_map<TNode, TNode>& cache) const
1400
{
1401
  // in cache?
1402
535
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1403
      cache.find(*this);
1404
535
  if(i != cache.end()) {
1405
42
    return (*i).second;
1406
  }
1407
1408
  // otherwise compute
1409
493
  Iterator j = find_if(
1410
      substitutionsBegin,
1411
      substitutionsEnd,
1412
4940
      [this](const auto& subst){ return subst.first == *this; });
1413
493
  if(j != substitutionsEnd) {
1414
308
    Node n = (*j).second;
1415
154
    cache[*this] = n;
1416
154
    return n;
1417
339
  } else if(getNumChildren() == 0) {
1418
180
    cache[*this] = *this;
1419
180
    return *this;
1420
  } else {
1421
318
    NodeBuilder nb(getKind());
1422
159
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1423
      // push the operator
1424
91
      nb << getOperator().substitute(substitutionsBegin, substitutionsEnd, cache);
1425
    }
1426
498
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1427
    {
1428
339
      nb << (*it).substitute(substitutionsBegin, substitutionsEnd, cache);
1429
    }
1430
318
    Node n = nb;
1431
159
    cache[*this] = n;
1432
159
    return n;
1433
  }
1434
}
1435
1436
#ifdef CVC5_DEBUG
1437
/**
1438
 * Pretty printer for use within gdb.  This is not intended to be used
1439
 * outside of gdb.  This writes to the Warning() stream and immediately
1440
 * flushes the stream.
1441
 *
1442
 * Note that this function cannot be a template, since the compiler
1443
 * won't instantiate it.  Even if we explicitly instantiate.  (Odd?)
1444
 * So we implement twice.  We mark as __attribute__((used)) so that
1445
 * GCC emits code for it even though static analysis indicates it's
1446
 * never called.
1447
 *
1448
 * Tim's Note: I moved this into the node.h file because this allows gdb
1449
 * to find the symbol, and use it, which is the first standard this code needs
1450
 * to meet. A cleaner solution is welcomed.
1451
 */
1452
static void __attribute__((used)) debugPrintNode(const NodeTemplate<true>& n) {
1453
  Warning() << Node::setdepth(-1)
1454
            << Node::dag(true)
1455
            << Node::setlanguage(language::output::LANG_AST)
1456
            << n << std::endl;
1457
  Warning().flush();
1458
}
1459
static void __attribute__((used)) debugPrintNodeNoDag(const NodeTemplate<true>& n) {
1460
  Warning() << Node::setdepth(-1)
1461
            << Node::dag(false)
1462
            << Node::setlanguage(language::output::LANG_AST)
1463
            << n << std::endl;
1464
  Warning().flush();
1465
}
1466
static void __attribute__((used)) debugPrintRawNode(const NodeTemplate<true>& n) {
1467
  n.printAst(Warning(), 0);
1468
  Warning().flush();
1469
}
1470
1471
static void __attribute__((used)) debugPrintTNode(const NodeTemplate<false>& n) {
1472
  Warning() << Node::setdepth(-1)
1473
            << Node::dag(true)
1474
            << Node::setlanguage(language::output::LANG_AST)
1475
            << n << std::endl;
1476
  Warning().flush();
1477
}
1478
static void __attribute__((used)) debugPrintTNodeNoDag(const NodeTemplate<false>& n) {
1479
  Warning() << Node::setdepth(-1)
1480
            << Node::dag(false)
1481
            << Node::setlanguage(language::output::LANG_AST)
1482
            << n << std::endl;
1483
  Warning().flush();
1484
}
1485
static void __attribute__((used)) debugPrintRawTNode(const NodeTemplate<false>& n) {
1486
  n.printAst(Warning(), 0);
1487
  Warning().flush();
1488
}
1489
#endif /* CVC5_DEBUG */
1490
1491
}  // namespace cvc5
1492
1493
#endif /* CVC5__NODE_H */