GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node.h Lines: 294 357 82.4 %
Date: 2021-05-22 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
25975111230
  inline void assertTNodeNotExpired() const
228
  {
229
    if(!ref_count) {
230
10343461324
      Assert(d_nv->d_rc > 0) << "TNode pointing to an expired NodeValue";
231
    }
232
25975111230
  }
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
928428348
 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
440674057
 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
3881946049
 bool isNull() const
319
 {
320
3881946049
   assertTNodeNotExpired();
321
3881946049
   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
3097644303
  bool operator==(const NodeTemplate<ref_count_1>& node) const {
331
3097644303
    assertTNodeNotExpired();
332
3097644303
    node.assertTNodeNotExpired();
333
3097644303
    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
129767970
  bool operator!=(const NodeTemplate<ref_count_1>& node) const {
343
129767970
    assertTNodeNotExpired();
344
129767970
    node.assertTNodeNotExpired();
345
129767970
    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
1267254437
  inline bool operator<(const NodeTemplate<ref_count_1>& node) const {
356
1267254437
    assertTNodeNotExpired();
357
1267254437
    node.assertTNodeNotExpired();
358
1267254437
    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
628461
  inline bool operator>(const NodeTemplate<ref_count_1>& node) const {
369
628461
    assertTNodeNotExpired();
370
628461
    node.assertTNodeNotExpired();
371
628461
    return d_nv->d_id > node.d_nv->d_id;
372
  }
373
374
  /**
375
   * We compare by expression ids so, keeping things deterministic and having
376
   * that subexpressions have to be smaller than the enclosing expressions.
377
   * @param node the node to compare to
378
   * @return true if this expression is smaller than or equal to
379
   */
380
  template <bool ref_count_1>
381
93
  inline bool operator<=(const NodeTemplate<ref_count_1>& node) const {
382
93
    assertTNodeNotExpired();
383
93
    node.assertTNodeNotExpired();
384
93
    return d_nv->d_id <= node.d_nv->d_id;
385
  }
386
387
  /**
388
   * We compare by expression ids so, keeping things deterministic and having
389
   * that subexpressions have to be smaller than the enclosing expressions.
390
   * @param node the node to compare to
391
   * @return true if this expression is greater than or equal to
392
   */
393
  template <bool ref_count_1>
394
39752
  inline bool operator>=(const NodeTemplate<ref_count_1>& node) const {
395
39752
    assertTNodeNotExpired();
396
39752
    node.assertTNodeNotExpired();
397
39752
    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
1144786985
  NodeTemplate operator[](int i) const {
406
1144786985
    assertTNodeNotExpired();
407
1144786985
    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
355140252
  inline bool isVar() const {
421
355140252
    assertTNodeNotExpired();
422
355140252
    return getMetaKind() == kind::metakind::VARIABLE;
423
  }
424
425
  /**
426
   * Returns true if this node represents a nullary operator
427
   */
428
3514
  inline bool isNullaryOp() const {
429
3514
    assertTNodeNotExpired();
430
3514
    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
42104948
  inline bool isClosure() const {
438
42104948
    assertTNodeNotExpired();
439
84203645
    return getKind() == kind::LAMBDA || getKind() == kind::FORALL
440
41692965
           || getKind() == kind::EXISTS || getKind() == kind::WITNESS
441
41691054
           || getKind() == kind::COMPREHENSION
442
83795190
           || getKind() == kind::MATCH_BIND_CASE;
443
  }
444
445
  /**
446
   * Returns the unique id of this node
447
   * @return the ud
448
   */
449
2197918351
  uint64_t getId() const
450
  {
451
2197918351
    assertTNodeNotExpired();
452
2197918351
    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
5392163905
  inline Kind getKind() const {
528
5392163905
    assertTNodeNotExpired();
529
5392163905
    return Kind(d_nv->d_kind);
530
  }
531
532
  /**
533
   * Returns the metakind of this node.
534
   * @return the metakind
535
   */
536
726555450
  inline kind::MetaKind getMetaKind() const {
537
726555450
    assertTNodeNotExpired();
538
726555450
    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
  typedef typename expr::NodeValue::iterator< NodeTemplate<ref_count> > const_iterator;
609
610
18
  class kinded_iterator {
611
    friend class NodeTemplate<ref_count>;
612
613
    NodeTemplate<ref_count> d_node;
614
    ssize_t d_child;
615
616
8
    kinded_iterator(TNode node, ssize_t child) :
617
      d_node(node),
618
8
      d_child(child) {
619
8
    }
620
621
    // These are factories to serve as clients to Node::begin<K>() and
622
    // Node::end<K>().
623
4
    static kinded_iterator begin(TNode n, Kind k) {
624
4
      return kinded_iterator(n, n.getKind() == k ? 0 : -2);
625
    }
626
4
    static kinded_iterator end(TNode n, Kind k) {
627
4
      return kinded_iterator(n, n.getKind() == k ? n.getNumChildren() : -1);
628
    }
629
630
  public:
631
    typedef NodeTemplate<ref_count> value_type;
632
    typedef std::ptrdiff_t difference_type;
633
    typedef NodeTemplate<ref_count>* pointer;
634
    typedef NodeTemplate<ref_count>& reference;
635
636
    kinded_iterator() :
637
      d_node(NodeTemplate<ref_count>::null()),
638
      d_child(-2) {
639
    }
640
641
8
    kinded_iterator(const kinded_iterator& i) :
642
      d_node(i.d_node),
643
8
      d_child(i.d_child) {
644
8
    }
645
646
8
    NodeTemplate<ref_count> operator*() {
647
8
      return d_child < 0 ? d_node : d_node[d_child];
648
    }
649
650
4
    bool operator==(const kinded_iterator& i) {
651
4
      return d_node == i.d_node && d_child == i.d_child;
652
    }
653
654
    bool operator!=(const kinded_iterator& i) {
655
      return !(*this == i);
656
    }
657
658
8
    kinded_iterator& operator++() {
659
8
      if(d_child != -1) {
660
8
        ++d_child;
661
      }
662
8
      return *this;
663
    }
664
665
8
    kinded_iterator operator++(int) {
666
8
      kinded_iterator i = *this;
667
8
      ++*this;
668
8
      return i;
669
    }
670
  };/* class NodeTemplate<ref_count>::kinded_iterator */
671
672
  typedef kinded_iterator const_kinded_iterator;
673
674
  /**
675
   * Returns the iterator pointing to the first child.
676
   * @return the iterator
677
   */
678
110379088
  inline iterator begin() {
679
110379088
    assertTNodeNotExpired();
680
110379088
    return d_nv->begin< NodeTemplate<ref_count> >();
681
  }
682
683
  /**
684
   * Returns the iterator pointing to the end of the children (one beyond the
685
   * last one).
686
   * @return the end of the children iterator.
687
   */
688
612634734
  inline iterator end() {
689
612634734
    assertTNodeNotExpired();
690
612634734
    return d_nv->end< NodeTemplate<ref_count> >();
691
  }
692
693
  /**
694
   * Returns the iterator pointing to the first child, if the node's
695
   * kind is the same as the parameter, otherwise returns the iterator
696
   * pointing to the node itself.  This is useful if you want to
697
   * pretend to iterate over a "unary" PLUS, for instance, since unary
698
   * PLUSes don't exist---begin(PLUS) will give an iterator over the
699
   * children if the node's a PLUS node, otherwise give an iterator
700
   * over the node itself, as if it were a unary PLUS.
701
   * @param kind the kind to match
702
   * @return the kinded_iterator iterating over this Node (if its kind
703
   * is not the passed kind) or its children
704
   */
705
4
  inline kinded_iterator begin(Kind kind) {
706
4
    assertTNodeNotExpired();
707
4
    return kinded_iterator::begin(*this, kind);
708
  }
709
710
  /**
711
   * Returns the iterator pointing to the end of the children (one
712
   * beyond the last one), if the node's kind is the same as the
713
   * parameter, otherwise returns the iterator pointing to the
714
   * one-of-the-node-itself.  This is useful if you want to pretend to
715
   * iterate over a "unary" PLUS, for instance, since unary PLUSes
716
   * don't exist---begin(PLUS) will give an iterator over the children
717
   * if the node's a PLUS node, otherwise give an iterator over the
718
   * node itself, as if it were a unary PLUS.
719
   * @param kind the kind to match
720
   * @return the kinded_iterator pointing off-the-end of this Node (if
721
   * its kind is not the passed kind) or off-the-end of its children
722
   */
723
4
  inline kinded_iterator end(Kind kind) {
724
4
    assertTNodeNotExpired();
725
4
    return kinded_iterator::end(*this, kind);
726
  }
727
728
  /**
729
   * Returns the const_iterator pointing to the first child.
730
   * @return the const_iterator
731
   */
732
97734017
  inline const_iterator begin() const {
733
97734017
    assertTNodeNotExpired();
734
97734017
    return d_nv->begin< NodeTemplate<ref_count> >();
735
  }
736
737
  /**
738
   * Returns the const_iterator pointing to the end of the children (one
739
   * beyond the last one.
740
   * @return the end of the children const_iterator.
741
   */
742
95892234
  inline const_iterator end() const {
743
95892234
    assertTNodeNotExpired();
744
95892234
    return d_nv->end< NodeTemplate<ref_count> >();
745
  }
746
747
  /**
748
   * Returns the iterator pointing to the first child, if the node's
749
   * kind is the same as the parameter, otherwise returns the iterator
750
   * pointing to the node itself.  This is useful if you want to
751
   * pretend to iterate over a "unary" PLUS, for instance, since unary
752
   * PLUSes don't exist---begin(PLUS) will give an iterator over the
753
   * children if the node's a PLUS node, otherwise give an iterator
754
   * over the node itself, as if it were a unary PLUS.
755
   * @param kind the kind to match
756
   * @return the kinded_iterator iterating over this Node (if its kind
757
   * is not the passed kind) or its children
758
   */
759
  inline const_kinded_iterator begin(Kind kind) const {
760
    assertTNodeNotExpired();
761
    return const_kinded_iterator::begin(*this, kind);
762
  }
763
764
  /**
765
   * Returns the iterator pointing to the end of the children (one
766
   * beyond the last one), if the node's kind is the same as the
767
   * parameter, otherwise returns the iterator pointing to the
768
   * one-of-the-node-itself.  This is useful if you want to pretend to
769
   * iterate over a "unary" PLUS, for instance, since unary PLUSes
770
   * don't exist---begin(PLUS) will give an iterator over the children
771
   * if the node's a PLUS node, otherwise give an iterator over the
772
   * node itself, as if it were a unary PLUS.
773
   * @param kind the kind to match
774
   * @return the kinded_iterator pointing off-the-end of this Node (if
775
   * its kind is not the passed kind) or off-the-end of its children
776
   */
777
  inline const_kinded_iterator end(Kind kind) const {
778
    assertTNodeNotExpired();
779
    return const_kinded_iterator::end(*this, kind);
780
  }
781
782
  /**
783
   * Converts this node into a string representation.
784
   * @return the string representation of this node.
785
   */
786
5884
  inline std::string toString() const {
787
5884
    assertTNodeNotExpired();
788
5884
    return d_nv->toString();
789
  }
790
791
  /**
792
   * Converts this node into a string representation and sends it to the
793
   * given stream
794
   *
795
   * @param out the stream to serialize this node to
796
   * @param toDepth the depth to which to print this expression, or -1 to
797
   * print it fully
798
   * @param language the language in which to output
799
   */
800
60238
  inline void toStream(
801
      std::ostream& out,
802
      int toDepth = -1,
803
      size_t dagThreshold = 1,
804
      OutputLanguage language = language::output::LANG_AUTO) const
805
  {
806
60238
    assertTNodeNotExpired();
807
60238
    d_nv->toStream(out, toDepth, dagThreshold, language);
808
60224
  }
809
810
  /**
811
   * IOStream manipulator to set the maximum depth of Nodes when
812
   * pretty-printing.  -1 means print to any depth.  E.g.:
813
   *
814
   *   // let a, b, c, and d be VARIABLEs
815
   *   Node n = nm->mkNode(OR, a, b, nm->mkNode(AND, c, nm->mkNode(NOT, d)))
816
   *   out << setdepth(3) << n;
817
   *
818
   * gives "(OR a b (AND c (NOT d)))", but
819
   *
820
   *   out << setdepth(1) << [same node as above]
821
   *
822
   * gives "(OR a b (...))"
823
   */
824
  typedef expr::ExprSetDepth setdepth;
825
826
  /**
827
   * IOStream manipulator to print expressions as DAGs (or not).
828
   */
829
  typedef expr::ExprDag dag;
830
831
  /**
832
   * IOStream manipulator to set the output language for Exprs.
833
   */
834
  typedef language::SetLanguage setlanguage;
835
836
  /**
837
   * Very basic pretty printer for Node.
838
   * @param out output stream to print to.
839
   * @param indent number of spaces to indent the formula by.
840
   */
841
  inline void printAst(std::ostream& out, int indent = 0) const;
842
843
  template <bool ref_count2>
844
  NodeTemplate<true> eqNode(const NodeTemplate<ref_count2>& right) const;
845
846
  NodeTemplate<true> notNode() const;
847
  NodeTemplate<true> negate() const;
848
  template <bool ref_count2>
849
  NodeTemplate<true> andNode(const NodeTemplate<ref_count2>& right) const;
850
  template <bool ref_count2>
851
  NodeTemplate<true> orNode(const NodeTemplate<ref_count2>& right) const;
852
  template <bool ref_count2, bool ref_count3>
853
  NodeTemplate<true> iteNode(const NodeTemplate<ref_count2>& thenpart,
854
                             const NodeTemplate<ref_count3>& elsepart) const;
855
  template <bool ref_count2>
856
  NodeTemplate<true> impNode(const NodeTemplate<ref_count2>& right) const;
857
  template <bool ref_count2>
858
  NodeTemplate<true> xorNode(const NodeTemplate<ref_count2>& right) const;
859
860
};/* class NodeTemplate<ref_count> */
861
862
/**
863
 * Serializes a given node to the given stream.
864
 *
865
 * @param out the output stream to use
866
 * @param n the node to output to the stream
867
 * @return the stream
868
 */
869
53986
inline std::ostream& operator<<(std::ostream& out, TNode n) {
870
107972
  n.toStream(out,
871
53986
             Node::setdepth::getDepth(out),
872
             Node::dag::getDag(out),
873
             Node::setlanguage::getLanguage(out));
874
53972
  return out;
875
}
876
877
/**
878
 * Serialize a vector of nodes to given stream.
879
 *
880
 * @param out the output stream to use
881
 * @param container the vector of nodes to output to the stream
882
 * @return the stream
883
 */
884
template <bool RC>
885
std::ostream& operator<<(std::ostream& out,
886
                         const std::vector<NodeTemplate<RC>>& container)
887
{
888
  container_to_stream(out, container);
889
  return out;
890
}
891
892
/**
893
 * Serialize a set of nodes to the given stream.
894
 *
895
 * @param out the output stream to use
896
 * @param container the set of nodes to output to the stream
897
 * @return the stream
898
 */
899
template <bool RC>
900
std::ostream& operator<<(std::ostream& out,
901
                         const std::set<NodeTemplate<RC>>& container)
902
{
903
  container_to_stream(out, container);
904
  return out;
905
}
906
907
/**
908
 * Serialize an unordered_set of nodes to the given stream.
909
 *
910
 * @param out the output stream to use
911
 * @param container the unordered_set of nodes to output to the stream
912
 * @return the stream
913
 */
914
template <bool RC, typename hash_function>
915
std::ostream& operator<<(
916
    std::ostream& out,
917
    const std::unordered_set<NodeTemplate<RC>, hash_function>& container)
918
{
919
  container_to_stream(out, container);
920
  return out;
921
}
922
923
/**
924
 * Serialize a map of nodes to the given stream.
925
 *
926
 * @param out the output stream to use
927
 * @param container the map of nodes to output to the stream
928
 * @return the stream
929
 */
930
template <bool RC, typename V>
931
std::ostream& operator<<(
932
    std::ostream& out,
933
    const std::map<NodeTemplate<RC>, V>& container)
934
{
935
  container_to_stream(out, container);
936
  return out;
937
}
938
939
/**
940
 * Serialize an unordered_map of nodes to the given stream.
941
 *
942
 * @param out the output stream to use
943
 * @param container the unordered_map of nodes to output to the stream
944
 * @return the stream
945
 */
946
template <bool RC, typename V, typename HF>
947
std::ostream& operator<<(
948
    std::ostream& out,
949
    const std::unordered_map<NodeTemplate<RC>, V, HF>& container)
950
{
951
  container_to_stream(out, container);
952
  return out;
953
}
954
955
}  // namespace cvc5
956
957
//#include "expr/attribute.h"
958
#include "expr/node_manager.h"
959
960
namespace cvc5 {
961
962
using TNodePairHashFunction =
963
    PairHashFunction<TNode, TNode, std::hash<TNode>, std::hash<TNode>>;
964
965
template <bool ref_count>
966
727594484
inline size_t NodeTemplate<ref_count>::getNumChildren() const {
967
727594484
  assertTNodeNotExpired();
968
727594484
  return d_nv->getNumChildren();
969
}
970
971
template <bool ref_count>
972
template <class T>
973
540247589
inline const T& NodeTemplate<ref_count>::getConst() const {
974
540247589
  assertTNodeNotExpired();
975
540247589
  return d_nv->getConst<T>();
976
}
977
978
template <bool ref_count>
979
template <class AttrKind>
980
127907907
inline typename AttrKind::value_type NodeTemplate<ref_count>::
981
getAttribute(const AttrKind&) const {
982
127907907
  Assert(NodeManager::currentNM() != NULL)
983
      << "There is no current cvc5::NodeManager associated to this thread.\n"
984
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
985
986
127907907
  assertTNodeNotExpired();
987
988
127907907
  return NodeManager::currentNM()->getAttribute(*this, AttrKind());
989
}
990
991
template <bool ref_count>
992
template <class AttrKind>
993
156077982
inline bool NodeTemplate<ref_count>::
994
hasAttribute(const AttrKind&) const {
995
156077982
  Assert(NodeManager::currentNM() != NULL)
996
      << "There is no current cvc5::NodeManager associated to this thread.\n"
997
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
998
999
156077982
  assertTNodeNotExpired();
1000
1001
156077982
  return NodeManager::currentNM()->hasAttribute(*this, AttrKind());
1002
}
1003
1004
template <bool ref_count>
1005
template <class AttrKind>
1006
79690616
inline bool NodeTemplate<ref_count>::getAttribute(const AttrKind&,
1007
                                                  typename AttrKind::value_type& ret) const {
1008
79690616
  Assert(NodeManager::currentNM() != NULL)
1009
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1010
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1011
1012
79690616
  assertTNodeNotExpired();
1013
1014
79690616
  return NodeManager::currentNM()->getAttribute(*this, AttrKind(), ret);
1015
}
1016
1017
template <bool ref_count>
1018
template <class AttrKind>
1019
39073344
inline void NodeTemplate<ref_count>::
1020
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) {
1021
39073344
  Assert(NodeManager::currentNM() != NULL)
1022
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1023
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1024
1025
39073344
  assertTNodeNotExpired();
1026
1027
39073344
  NodeManager::currentNM()->setAttribute(*this, AttrKind(), value);
1028
39073344
}
1029
1030
template <bool ref_count>
1031
3872358
NodeTemplate<ref_count> NodeTemplate<ref_count>::s_null(&expr::NodeValue::null());
1032
1033
// FIXME: escape from type system convenient but is there a better
1034
// way?  Nodes conceptually don't change their expr values but of
1035
// course they do modify the refcount.  But it's nice to be able to
1036
// support node_iterators over const NodeValue*.  So.... hm.
1037
template <bool ref_count>
1038
2229383578
NodeTemplate<ref_count>::NodeTemplate(const expr::NodeValue* ev) :
1039
2229383578
  d_nv(const_cast<expr::NodeValue*> (ev)) {
1040
2229383578
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1041
  if(ref_count) {
1042
1413220770
    d_nv->inc();
1043
  } else {
1044
816162808
    Assert(d_nv->d_rc > 0 || d_nv == &expr::NodeValue::null())
1045
        << "TNode constructed from NodeValue with rc == 0";
1046
  }
1047
2229383578
}
1048
1049
// the code for these two following constructors ("conversion/copy
1050
// constructors") is identical, but we need both.  see comment in the
1051
// class.
1052
1053
template <bool ref_count>
1054
4640642471
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate<!ref_count>& e) {
1055
4640642471
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1056
4640642471
  d_nv = e.d_nv;
1057
  if(ref_count) {
1058
1586892029
    Assert(d_nv->d_rc > 0) << "Node constructed from TNode with rc == 0";
1059
1586892029
    d_nv->inc();
1060
  } else {
1061
    // shouldn't ever fail
1062
3053750442
    Assert(d_nv->d_rc > 0) << "TNode constructed from Node with rc == 0";
1063
  }
1064
4640642471
}
1065
1066
template <bool ref_count>
1067
17586255615
NodeTemplate<ref_count>::NodeTemplate(const NodeTemplate& e) {
1068
17586255615
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value!";
1069
17586255615
  d_nv = e.d_nv;
1070
  if(ref_count) {
1071
    // shouldn't ever fail
1072
10163137779
    Assert(d_nv->d_rc > 0) << "Node constructed from Node with rc == 0";
1073
10163137779
    d_nv->inc();
1074
  } else {
1075
7423117836
    Assert(d_nv->d_rc > 0) << "TNode constructed from TNode with rc == 0";
1076
  }
1077
17586255615
}
1078
1079
template <bool ref_count>
1080
25384708857
NodeTemplate<ref_count>::~NodeTemplate() {
1081
25384708857
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1082
  if(ref_count) {
1083
    // shouldn't ever fail
1084
13953859670
    Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1085
13953859670
    d_nv->dec();
1086
  }
1087
25384708857
}
1088
1089
template <bool ref_count>
1090
void NodeTemplate<ref_count>::assignNodeValue(expr::NodeValue* ev) {
1091
  d_nv = ev;
1092
  if(ref_count) {
1093
    d_nv->inc();
1094
  } else {
1095
    Assert(d_nv->d_rc > 0) << "TNode assigned to NodeValue with rc == 0";
1096
  }
1097
}
1098
1099
template <bool ref_count>
1100
1119272242
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1101
operator=(const NodeTemplate& e) {
1102
1119272242
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1103
1119272242
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1104
1119272242
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1105
    if(ref_count) {
1106
      // shouldn't ever fail
1107
631847952
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1108
631847952
      d_nv->dec();
1109
    }
1110
724037324
    d_nv = e.d_nv;
1111
    if(ref_count) {
1112
      // shouldn't ever fail
1113
631847952
      Assert(d_nv->d_rc > 0) << "Node assigned from Node with rc == 0";
1114
631847952
      d_nv->inc();
1115
    } else {
1116
92189372
      Assert(d_nv->d_rc > 0) << "TNode assigned from TNode with rc == 0";
1117
    }
1118
  }
1119
1119272242
  return *this;
1120
}
1121
1122
template <bool ref_count>
1123
84819278
NodeTemplate<ref_count>& NodeTemplate<ref_count>::
1124
operator=(const NodeTemplate<!ref_count>& e) {
1125
84819278
  Assert(d_nv != NULL) << "Expecting a non-NULL expression value!";
1126
84819278
  Assert(e.d_nv != NULL) << "Expecting a non-NULL expression value on RHS!";
1127
84819278
  if(__builtin_expect( ( d_nv != e.d_nv ), true )) {
1128
    if(ref_count) {
1129
      // shouldn't ever fail
1130
9798187
      Assert(d_nv->d_rc > 0) << "Node reference count would be negative";
1131
9798187
      d_nv->dec();
1132
    }
1133
82955320
    d_nv = e.d_nv;
1134
    if(ref_count) {
1135
9798187
      Assert(d_nv->d_rc > 0) << "Node assigned from TNode with rc == 0";
1136
9798187
      d_nv->inc();
1137
    } else {
1138
      // shouldn't ever happen
1139
73157133
      Assert(d_nv->d_rc > 0) << "TNode assigned from Node with rc == 0";
1140
    }
1141
  }
1142
84819278
  return *this;
1143
}
1144
1145
template <bool ref_count>
1146
template <bool ref_count2>
1147
NodeTemplate<true>
1148
26881107
NodeTemplate<ref_count>::eqNode(const NodeTemplate<ref_count2>& right) const {
1149
26881107
  assertTNodeNotExpired();
1150
26881107
  return NodeManager::currentNM()->mkNode(kind::EQUAL, *this, right);
1151
}
1152
1153
template <bool ref_count>
1154
40385665
NodeTemplate<true> NodeTemplate<ref_count>::notNode() const {
1155
40385665
  assertTNodeNotExpired();
1156
40385665
  return NodeManager::currentNM()->mkNode(kind::NOT, *this);
1157
}
1158
1159
template <bool ref_count>
1160
8014554
NodeTemplate<true> NodeTemplate<ref_count>::negate() const {
1161
8014554
  assertTNodeNotExpired();
1162
8014554
  return (getKind() == kind::NOT) ? NodeTemplate<true>(d_nv->getChild(0)) : NodeManager::currentNM()->mkNode(kind::NOT, *this);
1163
}
1164
1165
template <bool ref_count>
1166
template <bool ref_count2>
1167
NodeTemplate<true>
1168
149809
NodeTemplate<ref_count>::andNode(const NodeTemplate<ref_count2>& right) const {
1169
149809
  assertTNodeNotExpired();
1170
149809
  return NodeManager::currentNM()->mkNode(kind::AND, *this, right);
1171
}
1172
1173
template <bool ref_count>
1174
template <bool ref_count2>
1175
NodeTemplate<true>
1176
89569
NodeTemplate<ref_count>::orNode(const NodeTemplate<ref_count2>& right) const {
1177
89569
  assertTNodeNotExpired();
1178
89569
  return NodeManager::currentNM()->mkNode(kind::OR, *this, right);
1179
}
1180
1181
template <bool ref_count>
1182
template <bool ref_count2, bool ref_count3>
1183
NodeTemplate<true>
1184
263599
NodeTemplate<ref_count>::iteNode(const NodeTemplate<ref_count2>& thenpart,
1185
                                 const NodeTemplate<ref_count3>& elsepart) const {
1186
263599
  assertTNodeNotExpired();
1187
263599
  return NodeManager::currentNM()->mkNode(kind::ITE, *this, thenpart, elsepart);
1188
}
1189
1190
template <bool ref_count>
1191
template <bool ref_count2>
1192
NodeTemplate<true>
1193
91614
NodeTemplate<ref_count>::impNode(const NodeTemplate<ref_count2>& right) const {
1194
91614
  assertTNodeNotExpired();
1195
91614
  return NodeManager::currentNM()->mkNode(kind::IMPLIES, *this, right);
1196
}
1197
1198
template <bool ref_count>
1199
template <bool ref_count2>
1200
NodeTemplate<true>
1201
92
NodeTemplate<ref_count>::xorNode(const NodeTemplate<ref_count2>& right) const {
1202
92
  assertTNodeNotExpired();
1203
92
  return NodeManager::currentNM()->mkNode(kind::XOR, *this, right);
1204
}
1205
1206
template <bool ref_count>
1207
inline void
1208
NodeTemplate<ref_count>::printAst(std::ostream& out, int indent) const {
1209
  assertTNodeNotExpired();
1210
  d_nv->printAst(out, indent);
1211
}
1212
1213
/**
1214
 * Returns a node representing the operator of this expression.
1215
 * If this is an APPLY_UF, then the operator will be a functional term.
1216
 * Otherwise, it will be a node with kind BUILTIN.
1217
 */
1218
template <bool ref_count>
1219
30343010
NodeTemplate<true> NodeTemplate<ref_count>::getOperator() const
1220
{
1221
30343010
  Assert(NodeManager::currentNM() != NULL)
1222
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1223
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1224
1225
30343010
  assertTNodeNotExpired();
1226
1227
30343010
  kind::MetaKind mk = getMetaKind();
1228
30343010
  if (mk == kind::metakind::OPERATOR)
1229
  {
1230
    /* Returns a BUILTIN node. */
1231
5389131
    return NodeManager::currentNM()->operatorOf(getKind());
1232
  }
1233
24953879
  Assert(mk == kind::metakind::PARAMETERIZED);
1234
  /* The operator is the first child. */
1235
24953879
  return Node(d_nv->d_children[0]);
1236
}
1237
1238
/**
1239
 * Returns true if the node has an operator (i.e., it's not a variable
1240
 * or a constant).
1241
 */
1242
template <bool ref_count>
1243
14772108
inline bool NodeTemplate<ref_count>::hasOperator() const {
1244
14772108
  assertTNodeNotExpired();
1245
14772108
  return NodeManager::hasOperator(getKind());
1246
}
1247
1248
template <bool ref_count>
1249
475797848
TypeNode NodeTemplate<ref_count>::getType(bool check) const
1250
{
1251
475797848
  Assert(NodeManager::currentNM() != NULL)
1252
      << "There is no current cvc5::NodeManager associated to this thread.\n"
1253
         "Perhaps a public-facing function is missing a NodeManagerScope ?";
1254
1255
475797848
  assertTNodeNotExpired();
1256
1257
475797849
  return NodeManager::currentNM()->getType(*this, check);
1258
}
1259
1260
template <bool ref_count>
1261
inline Node
1262
113536
NodeTemplate<ref_count>::substitute(TNode node, TNode replacement) const {
1263
113536
  if (node == *this) {
1264
3968
    return replacement;
1265
  }
1266
219136
  std::unordered_map<TNode, TNode> cache;
1267
109568
  return substitute(node, replacement, cache);
1268
}
1269
1270
template <bool ref_count>
1271
10239211
Node NodeTemplate<ref_count>::substitute(
1272
    TNode node,
1273
    TNode replacement,
1274
    std::unordered_map<TNode, TNode>& cache) const
1275
{
1276
10239211
  Assert(node != *this);
1277
1278
10239211
  if (getNumChildren() == 0 || node == replacement)
1279
  {
1280
3240782
    return *this;
1281
  }
1282
1283
  // in cache?
1284
6998429
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1285
      cache.find(*this);
1286
6998429
  if(i != cache.end()) {
1287
2794875
    return (*i).second;
1288
  }
1289
1290
  // otherwise compute
1291
8407108
  NodeBuilder nb(getKind());
1292
4203554
  if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1293
    // push the operator
1294
1202211
    if(getOperator() == node) {
1295
155
      nb << replacement;
1296
    } else {
1297
1202056
      nb << getOperator().substitute(node, replacement, cache);
1298
    }
1299
  }
1300
13349997
  for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1301
  {
1302
9146443
    if (*it == node)
1303
    {
1304
607375
      nb << replacement;
1305
    }
1306
    else
1307
    {
1308
8539068
      nb << (*it).substitute(node, replacement, cache);
1309
    }
1310
  }
1311
1312
  // put in cache
1313
8407108
  Node n = nb;
1314
4203554
  cache[*this] = n;
1315
4203554
  return n;
1316
}
1317
1318
template <bool ref_count>
1319
template <class Iterator1, class Iterator2>
1320
inline Node
1321
9355463
NodeTemplate<ref_count>::substitute(Iterator1 nodesBegin,
1322
                                    Iterator1 nodesEnd,
1323
                                    Iterator2 replacementsBegin,
1324
                                    Iterator2 replacementsEnd) const {
1325
18710926
  std::unordered_map<TNode, TNode> cache;
1326
  return substitute(nodesBegin, nodesEnd,
1327
18710926
                    replacementsBegin, replacementsEnd, cache);
1328
}
1329
1330
template <bool ref_count>
1331
template <class Iterator1, class Iterator2>
1332
42918505
Node NodeTemplate<ref_count>::substitute(
1333
    Iterator1 nodesBegin,
1334
    Iterator1 nodesEnd,
1335
    Iterator2 replacementsBegin,
1336
    Iterator2 replacementsEnd,
1337
    std::unordered_map<TNode, TNode>& cache) const
1338
{
1339
  // in cache?
1340
42918505
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1341
      cache.find(*this);
1342
42918505
  if(i != cache.end()) {
1343
11761911
    return (*i).second;
1344
  }
1345
1346
  // otherwise compute
1347
31156594
  Assert(std::distance(nodesBegin, nodesEnd)
1348
         == std::distance(replacementsBegin, replacementsEnd))
1349
      << "Substitution iterator ranges must be equal size";
1350
31156594
  Iterator1 j = std::find(nodesBegin, nodesEnd, TNode(*this));
1351
31156594
  if(j != nodesEnd) {
1352
2871651
    Iterator2 b = replacementsBegin;
1353
2871651
    std::advance(b, std::distance(nodesBegin, j));
1354
5743302
    Node n = *b;
1355
2871651
    cache[*this] = n;
1356
2871651
    return n;
1357
28284943
  } else if(getNumChildren() == 0) {
1358
14874386
    cache[*this] = *this;
1359
14874386
    return *this;
1360
  } else {
1361
26821114
    NodeBuilder nb(getKind());
1362
13410557
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1363
      // push the operator
1364
1618523
      nb << getOperator().substitute(nodesBegin, nodesEnd,
1365
                                     replacementsBegin, replacementsEnd,
1366
                                     cache);
1367
    }
1368
45355076
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1369
    {
1370
31944519
      nb << (*it).substitute(
1371
          nodesBegin, nodesEnd, replacementsBegin, replacementsEnd, cache);
1372
    }
1373
26821114
    Node n = nb;
1374
13410557
    cache[*this] = n;
1375
13410557
    return n;
1376
  }
1377
}
1378
1379
template <bool ref_count>
1380
template <class Iterator>
1381
inline Node
1382
106
NodeTemplate<ref_count>::substitute(Iterator substitutionsBegin,
1383
                                    Iterator substitutionsEnd) const {
1384
212
  std::unordered_map<TNode, TNode> cache;
1385
212
  return substitute(substitutionsBegin, substitutionsEnd, cache);
1386
}
1387
1388
template <bool ref_count>
1389
6
inline Node NodeTemplate<ref_count>::substitute(
1390
    std::unordered_map<TNode, TNode>& cache) const
1391
{
1392
  // Since no substitution is given (other than what may already be in the
1393
  // cache), we pass dummy iterators to conform to the main substitute method,
1394
  // giving the same value to substitutionsBegin and substitutionsEnd.
1395
6
  return substitute(cache.cend(), cache.cend(), cache);
1396
}
1397
1398
template <bool ref_count>
1399
template <class Iterator>
1400
582
Node NodeTemplate<ref_count>::substitute(
1401
    Iterator substitutionsBegin,
1402
    Iterator substitutionsEnd,
1403
    std::unordered_map<TNode, TNode>& cache) const
1404
{
1405
  // in cache?
1406
582
  typename std::unordered_map<TNode, TNode>::const_iterator i =
1407
      cache.find(*this);
1408
582
  if(i != cache.end()) {
1409
55
    return (*i).second;
1410
  }
1411
1412
  // otherwise compute
1413
527
  Iterator j = find_if(
1414
      substitutionsBegin,
1415
      substitutionsEnd,
1416
5045
      [this](const auto& subst){ return subst.first == *this; });
1417
527
  if(j != substitutionsEnd) {
1418
320
    Node n = (*j).second;
1419
160
    cache[*this] = n;
1420
160
    return n;
1421
367
  } else if(getNumChildren() == 0) {
1422
197
    cache[*this] = *this;
1423
197
    return *this;
1424
  } else {
1425
340
    NodeBuilder nb(getKind());
1426
170
    if(getMetaKind() == kind::metakind::PARAMETERIZED) {
1427
      // push the operator
1428
102
      nb << getOperator().substitute(substitutionsBegin, substitutionsEnd, cache);
1429
    }
1430
538
    for (const_iterator it = begin(), iend = end(); it != iend; ++it)
1431
    {
1432
368
      nb << (*it).substitute(substitutionsBegin, substitutionsEnd, cache);
1433
    }
1434
340
    Node n = nb;
1435
170
    cache[*this] = n;
1436
170
    return n;
1437
  }
1438
}
1439
1440
#ifdef CVC5_DEBUG
1441
/**
1442
 * Pretty printer for use within gdb.  This is not intended to be used
1443
 * outside of gdb.  This writes to the Warning() stream and immediately
1444
 * flushes the stream.
1445
 *
1446
 * Note that this function cannot be a template, since the compiler
1447
 * won't instantiate it.  Even if we explicitly instantiate.  (Odd?)
1448
 * So we implement twice.  We mark as __attribute__((used)) so that
1449
 * GCC emits code for it even though static analysis indicates it's
1450
 * never called.
1451
 *
1452
 * Tim's Note: I moved this into the node.h file because this allows gdb
1453
 * to find the symbol, and use it, which is the first standard this code needs
1454
 * to meet. A cleaner solution is welcomed.
1455
 */
1456
static void __attribute__((used)) debugPrintNode(const NodeTemplate<true>& n) {
1457
  Warning() << Node::setdepth(-1)
1458
            << Node::dag(true)
1459
            << Node::setlanguage(language::output::LANG_AST)
1460
            << n << std::endl;
1461
  Warning().flush();
1462
}
1463
static void __attribute__((used)) debugPrintNodeNoDag(const NodeTemplate<true>& n) {
1464
  Warning() << Node::setdepth(-1)
1465
            << Node::dag(false)
1466
            << Node::setlanguage(language::output::LANG_AST)
1467
            << n << std::endl;
1468
  Warning().flush();
1469
}
1470
static void __attribute__((used)) debugPrintRawNode(const NodeTemplate<true>& n) {
1471
  n.printAst(Warning(), 0);
1472
  Warning().flush();
1473
}
1474
1475
static void __attribute__((used)) debugPrintTNode(const NodeTemplate<false>& n) {
1476
  Warning() << Node::setdepth(-1)
1477
            << Node::dag(true)
1478
            << Node::setlanguage(language::output::LANG_AST)
1479
            << n << std::endl;
1480
  Warning().flush();
1481
}
1482
static void __attribute__((used)) debugPrintTNodeNoDag(const NodeTemplate<false>& n) {
1483
  Warning() << Node::setdepth(-1)
1484
            << Node::dag(false)
1485
            << Node::setlanguage(language::output::LANG_AST)
1486
            << n << std::endl;
1487
  Warning().flush();
1488
}
1489
static void __attribute__((used)) debugPrintRawTNode(const NodeTemplate<false>& n) {
1490
  n.printAst(Warning(), 0);
1491
  Warning().flush();
1492
}
1493
#endif /* CVC5_DEBUG */
1494
1495
}  // namespace cvc5
1496
1497
#endif /* CVC5__NODE_H */