GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node_traversal.h Lines: 5 5 100.0 %
Date: 2021-05-22 Branches: 4 8 50.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Alex Ozdemir, Andres Noetzli
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
 * Iterators for traversing nodes.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__EXPR__NODE_TRAVERSAL_H
19
#define CVC5__EXPR__NODE_TRAVERSAL_H
20
21
#include <iterator>
22
#include <unordered_map>
23
#include <vector>
24
25
#include "expr/node.h"
26
27
namespace cvc5 {
28
29
/**
30
 * Enum that represents an order in which nodes are visited.
31
 */
32
enum class VisitOrder
33
{
34
  PREORDER,
35
  POSTORDER
36
};
37
38
// Iterator for traversing a node in pre-/post-order
39
// It does DAG-traversal, so indentical sub-nodes will be visited once only.
40
class NodeDfsIterator
41
{
42
 public:
43
  // STL type definitions for an iterator
44
  using value_type = TNode;
45
  using pointer = TNode*;
46
  using reference = TNode&;
47
  using iterator_category = std::forward_iterator_tag;
48
  using difference_type = std::ptrdiff_t;
49
50
  // Construct a traversal iterator beginning at `n`
51
  NodeDfsIterator(TNode n, VisitOrder order, std::function<bool(TNode)> skipIf);
52
  // Construct an end-of-traversal iterator
53
  NodeDfsIterator(VisitOrder order);
54
55
  // Move/copy construction and assignment. Destructor.
56
40
  NodeDfsIterator(NodeDfsIterator&&) = default;
57
  NodeDfsIterator& operator=(NodeDfsIterator&&) = default;
58
96
  NodeDfsIterator(NodeDfsIterator&) = default;
59
  NodeDfsIterator& operator=(NodeDfsIterator&) = default;
60
2384
  ~NodeDfsIterator() = default;
61
62
  // Preincrement
63
  NodeDfsIterator& operator++();
64
  // Postincrement
65
  NodeDfsIterator operator++(int);
66
  // Dereference
67
  reference operator*();
68
  // Equals
69
  // It is not constant, because an unitilized node must be initialized before
70
  // comparison
71
  bool operator==(NodeDfsIterator&);
72
  // Not equals
73
  // It is not constant, because an unitilized node must be initialized before
74
  // comparison
75
  bool operator!=(NodeDfsIterator&);
76
77
 private:
78
  // While we're not at an appropriate visit (see d_postorder), advance.
79
  // In each step:
80
  //   * enqueue children of a not-yet-pre-visited node (and mark it
81
  //     previsited)
82
  //   * pop a not-yet-post-visited node (and mark it post-visited)
83
  //   * pop an already post-visited node.
84
  // After calling this, `d_current` will be changed to the next node, if there
85
  // is another node in the traversal.
86
  void advanceToNextVisit();
87
88
  // If this iterator hasn't been dereferenced or incremented yet, advance to
89
  // first visit.
90
  // Necessary because we are lazy and don't find our first visit node at
91
  // construction time.
92
  void initializeIfUninitialized();
93
94
  // Stack of nodes to visit.
95
  std::vector<TNode> d_stack;
96
97
  // Whether (and how) we've visited a node.
98
  // Absent if we haven't visited it.
99
  // Set to `false` if we've already pre-visited it (enqueued its children).
100
  // Set to `true` if we've also already post-visited it.
101
  std::unordered_map<TNode, bool> d_visited;
102
103
  // The visit order that this iterator is using
104
  VisitOrder d_order;
105
106
  // Current referent node. A valid node to visit if non-null.
107
  // Null after construction (but before first access) and at the end.
108
  TNode d_current;
109
110
  // When to omit a node and its descendants from the traversal
111
  std::function<bool(TNode)> d_skipIf;
112
};
113
114
// Node wrapper that is iterable in DAG pre-/post-order
115
class NodeDfsIterable
116
{
117
 public:
118
  /**
119
   * Creates a new node wrapper that can be used to iterate over the children
120
   * of a node in pre-/post-order.
121
   *
122
   * @param n The node the iterate
123
   * @param order The order in which the children are visited.
124
   * @param skipIf Function that determines whether a given node and its
125
   *               descendants should be skipped or not.
126
   */
127
  NodeDfsIterable(
128
      TNode n,
129
      VisitOrder order = VisitOrder::POSTORDER,
130
90
      std::function<bool(TNode)> skipIf = [](TNode) { return false; });
131
132
  // Move/copy construction and assignment. Destructor.
133
  NodeDfsIterable(NodeDfsIterable&&) = default;
134
  NodeDfsIterable& operator=(NodeDfsIterable&&) = default;
135
  NodeDfsIterable(NodeDfsIterable&) = default;
136
  NodeDfsIterable& operator=(NodeDfsIterable&) = default;
137
1124
  ~NodeDfsIterable() = default;
138
139
  NodeDfsIterator begin() const;
140
  NodeDfsIterator end() const;
141
142
 private:
143
  TNode d_node;
144
  VisitOrder d_order;
145
  std::function<bool(TNode)> d_skipIf;
146
};
147
148
}  // namespace cvc5
149
150
#endif  // CVC5__EXPR__NODE_TRAVERSAL_H