1 /********************* */
4 ** Original author: Dejan Jovanovic
5 ** Major contributors: Morgan Deters
6 ** Minor contributors (to current version): Kshitij Bansal, Francois Bobot, Clark Barrett, Tim King, Christopher L. Conway
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2014 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
12 ** \brief Reference-counted encapsulation of a pointer to node information
14 ** Reference-counted encapsulation of a pointer to node information.
17 #include "cvc4_private.h"
19 // circular dependency
20 #include "expr/node_value.h"
22 #ifndef __CVC4__NODE_H
23 #define __CVC4__NODE_H
33 #include "base/cvc4_assert.h"
34 #include "base/exception.h"
35 #include "base/output.h"
36 #include "expr/type.h"
37 #include "expr/kind.h"
38 #include "expr/metakind.h"
39 #include "expr/expr.h"
40 #include "expr/expr_iomanip.h"
41 #include "options/language.h"
42 #include "options/set_language.h"
43 #include "util/configuration.h"
44 #include "util/utility.h"
45 #include "util/hash.h"
55 }/* CVC4::expr::pickle namespace */
56 }/* CVC4::expr namespace */
58 template <bool ref_count
>
62 * Exception thrown during the type-checking phase, it can be
63 * thrown by node.getType().
65 class TypeCheckingExceptionPrivate
: public Exception
{
69 /** The node responsible for the failure */
70 NodeTemplate
<true>* d_node
;
75 * Construct the exception with the problematic node and the message
76 * @param node the problematic node
77 * @param message the message explaining the failure
79 TypeCheckingExceptionPrivate(NodeTemplate
<false> node
, std::string message
) throw();
82 ~TypeCheckingExceptionPrivate() throw ();
85 * Get the Node that caused the type-checking to fail.
88 NodeTemplate
<true> getNode() const throw();
91 * Returns the message corresponding to the type-checking failure.
92 * We prefer toStream() to toString() because that keeps the expr-depth
93 * and expr-language settings present in the stream.
95 void toStream(std::ostream
& out
) const throw();
97 };/* class TypeCheckingExceptionPrivate */
99 class UnknownTypeException
: public TypeCheckingExceptionPrivate
{
102 UnknownTypeException(NodeTemplate
<false> node
) throw();
104 };/* class UnknownTypeException */
107 * \typedef NodeTemplate<true> Node;
109 * The Node class encapsulates the NodeValue with reference counting.
111 * One should use generally use Nodes to manipulate expressions, to be safe.
112 * Every outstanding Node that references a NodeValue is counted in that
113 * NodeValue's reference count. Reference counts are maintained correctly
114 * on assignment of the Node object (to point to another NodeValue), and,
115 * upon destruction of the Node object, the NodeValue's reference count is
116 * decremented and, if zero, it becomes eligible for reclamation by the
119 typedef NodeTemplate
<true> Node
;
122 * \typedef NodeTemplate<false> TNode;
124 * The TNode class encapsulates the NodeValue but doesn't count references.
126 * TNodes are just like Nodes, but they don't update the reference count.
127 * Therefore, there is less overhead (copying a TNode is just the cost of
128 * the underlying pointer copy). Generally speaking, this is unsafe!
129 * However, there are certain situations where a TNode can be used safely.
131 * The largest class of uses for TNodes are when you need to use them in a
132 * "temporary," scoped fashion (hence the "T" in "TNode"). In general,
133 * it is safe to use TNode as a function parameter type, since the calling
134 * function (or some other function on the call stack) presumably has a Node
135 * reference to the expression data. It is generally _not_ safe, however,
136 * to return a TNode _from_ a function. (Functions that return Nodes often
137 * create the expression they return; such new expressions may not be
138 * referenced on the call stack, and have a reference count of 1 on
139 * creation. If this is returned as a TNode rather than a Node, the
140 * count drops to zero, marking the expression as eligible for reclamation.)
142 * More guidelines on when to use TNodes is available in the CVC4
144 * http://goedel.cims.nyu.edu/wiki/Developer%27s_Guide#Dealing_with_expressions_.28Nodes_and_TNodes.29
146 typedef NodeTemplate
<false> TNode
;
153 class AttributeManager
;
154 struct SmtAttributes
;
155 }/* CVC4::expr::attr namespace */
158 }/* CVC4::expr namespace */
162 struct NodeValueConstPrinter
;
163 }/* CVC4::kind::metakind namespace */
164 }/* CVC4::kind namespace */
166 // for hash_maps, hash_sets..
167 struct NodeHashFunction
{
168 inline size_t operator()(Node node
) const;
169 };/* struct NodeHashFunction */
170 struct TNodeHashFunction
{
171 inline size_t operator()(TNode node
) const;
172 };/* struct TNodeHashFunction */
175 * Encapsulation of an NodeValue pointer. The reference count is
176 * maintained in the NodeValue if ref_count is true.
177 * @param ref_count if true reference are counted in the NodeValue
179 template <bool ref_count
>
182 * The NodeValue has access to the private constructors, so that the
183 * iterators can can create new nodes.
185 friend class expr::NodeValue
;
187 friend class expr::pickle::PicklerPrivate
;
188 friend class expr::ExportPrivate
;
190 /** A convenient null-valued encapsulated pointer */
191 static NodeTemplate s_null
;
193 /** The referenced NodeValue */
194 expr::NodeValue
* d_nv
;
197 * This constructor is reserved for use by the NodeTemplate package; one
198 * must construct an NodeTemplate using one of the build mechanisms of the
199 * NodeTemplate package.
201 * FIXME: there's a type-system escape here to cast away the const,
202 * since the refcount needs to be updated. But conceptually Nodes
203 * don't change their arguments, and it's nice to have
204 * const_iterators over them.
206 * This really does needs to be explicit to avoid hard to track errors with
207 * Nodes implicitly wrapping NodeValues
209 explicit NodeTemplate(const expr::NodeValue
*);
211 friend class NodeTemplate
<true>;
212 friend class NodeTemplate
<false>;
213 friend class TypeNode
;
214 friend class NodeManager
;
216 template <unsigned nchild_thresh
>
217 friend class NodeBuilder
;
219 friend class ::CVC4::expr::attr::AttributeManager
;
220 friend struct ::CVC4::expr::attr::SmtAttributes
;
222 friend struct ::CVC4::kind::metakind::NodeValueConstPrinter
;
225 * Assigns the expression value and does reference counting. No assumptions
226 * are made on the expression, and should only be used if we know what we
229 * @param ev the expression value to assign
231 void assignNodeValue(expr::NodeValue
* ev
);
233 inline void assertTNodeNotExpired() const throw(AssertionException
) {
235 Assert( d_nv
->d_rc
> 0, "TNode pointing to an expired NodeValue" );
242 * Cache-aware, recursive version of substitute() used by the public
243 * member function with a similar signature.
245 Node
substitute(TNode node
, TNode replacement
,
246 std::hash_map
<TNode
, TNode
, TNodeHashFunction
>& cache
) const;
249 * Cache-aware, recursive version of substitute() used by the public
250 * member function with a similar signature.
252 template <class Iterator1
, class Iterator2
>
253 Node
substitute(Iterator1 nodesBegin
, Iterator1 nodesEnd
,
254 Iterator2 replacementsBegin
, Iterator2 replacementsEnd
,
255 std::hash_map
<TNode
, TNode
, TNodeHashFunction
>& cache
) const;
258 * Cache-aware, recursive version of substitute() used by the public
259 * member function with a similar signature.
261 template <class Iterator
>
262 Node
substitute(Iterator substitutionsBegin
, Iterator substitutionsEnd
,
263 std::hash_map
<TNode
, TNode
, TNodeHashFunction
>& cache
) const;
265 /** Default constructor, makes a null expression. */
266 NodeTemplate() : d_nv(&expr::NodeValue::null()) { }
269 * Conversion between nodes that are reference-counted and those that are
271 * @param node the node to make copy of
273 NodeTemplate(const NodeTemplate
<!ref_count
>& node
);
276 * Copy constructor. Note that GCC does NOT recognize an instantiation of
277 * the above template as a copy constructor and problems ensue. So we
278 * provide an explicit one here.
279 * @param node the node to make copy of
281 NodeTemplate(const NodeTemplate
& node
);
284 * Allow Exprs to become Nodes. This permits flexible translation of
285 * Exprs -> Nodes inside the CVC4 library without exposing a toNode()
286 * function in the public interface, or requiring lots of "friend"
289 NodeTemplate(const Expr
& e
);
292 * Assignment operator for nodes, copies the relevant information from node
294 * @param node the node to copy
295 * @return reference to this node
297 NodeTemplate
& operator=(const NodeTemplate
& node
);
300 * Assignment operator for nodes, copies the relevant information from node
302 * @param node the node to copy
303 * @return reference to this node
305 NodeTemplate
& operator=(const NodeTemplate
<!ref_count
>& node
);
308 * Destructor. If ref_count is true it will decrement the reference count
309 * and, if zero, collect the NodeValue.
311 ~NodeTemplate() throw(AssertionException
);
314 * Return the null node.
315 * @return the null node
317 static NodeTemplate
null() {
322 * Returns true if this expression is a null expression.
323 * @return true if null
325 bool isNull() const {
326 assertTNodeNotExpired();
327 return d_nv
== &expr::NodeValue::null();
331 * Structural comparison operator for expressions.
332 * @param node the node to compare to
333 * @return true if expressions are equal, false otherwise
335 template <bool ref_count_1
>
336 bool operator==(const NodeTemplate
<ref_count_1
>& node
) const {
337 assertTNodeNotExpired();
338 node
.assertTNodeNotExpired();
339 return d_nv
== node
.d_nv
;
343 * Structural comparison operator for expressions.
344 * @param node the node to compare to
345 * @return false if expressions are equal, true otherwise
347 template <bool ref_count_1
>
348 bool operator!=(const NodeTemplate
<ref_count_1
>& node
) const {
349 assertTNodeNotExpired();
350 node
.assertTNodeNotExpired();
351 return d_nv
!= node
.d_nv
;
355 * We compare by expression ids so, keeping things deterministic and having
356 * that subexpressions have to be smaller than the enclosing expressions.
357 * @param node the node to compare to
358 * @return true if this expression is smaller
360 template <bool ref_count_1
>
361 inline bool operator<(const NodeTemplate
<ref_count_1
>& node
) const {
362 assertTNodeNotExpired();
363 node
.assertTNodeNotExpired();
364 return d_nv
->d_id
< node
.d_nv
->d_id
;
368 * We compare by expression ids so, keeping things deterministic and having
369 * that subexpressions have to be smaller than the enclosing expressions.
370 * @param node the node to compare to
371 * @return true if this expression is greater
373 template <bool ref_count_1
>
374 inline bool operator>(const NodeTemplate
<ref_count_1
>& node
) const {
375 assertTNodeNotExpired();
376 node
.assertTNodeNotExpired();
377 return d_nv
->d_id
> node
.d_nv
->d_id
;
381 * We compare by expression ids so, keeping things deterministic and having
382 * that subexpressions have to be smaller than the enclosing expressions.
383 * @param node the node to compare to
384 * @return true if this expression is smaller than or equal to
386 template <bool ref_count_1
>
387 inline bool operator<=(const NodeTemplate
<ref_count_1
>& node
) const {
388 assertTNodeNotExpired();
389 node
.assertTNodeNotExpired();
390 return d_nv
->d_id
<= node
.d_nv
->d_id
;
394 * We compare by expression ids so, keeping things deterministic and having
395 * that subexpressions have to be smaller than the enclosing expressions.
396 * @param node the node to compare to
397 * @return true if this expression is greater than or equal to
399 template <bool ref_count_1
>
400 inline bool operator>=(const NodeTemplate
<ref_count_1
>& node
) const {
401 assertTNodeNotExpired();
402 node
.assertTNodeNotExpired();
403 return d_nv
->d_id
>= node
.d_nv
->d_id
;
407 * Returns the i-th child of this node.
408 * @param i the index of the child
409 * @return the node representing the i-th child
411 NodeTemplate
operator[](int i
) const {
412 assertTNodeNotExpired();
413 return NodeTemplate(d_nv
->getChild(i
));
416 /* A note on isAtomic() and isAtomicFormula() (in CVC3 parlance)..
418 * It has been decided for now to hold off on implementations of
419 * these functions, as they may only be needed in CNF conversion,
420 * where it's pointless to do a lazy isAtomic determination by
421 * searching through the DAG, and storing it, since the result will
422 * only be used once. For more details see the 4/27/2010 CVC4
423 * developer's meeting notes at:
425 * http://goedel.cims.nyu.edu/wiki/Meeting_Minutes_-_April_27,_2010#isAtomic.28.29_and_isAtomicFormula.28.29
427 // bool containsDecision(); // is "atomic"
428 // bool properlyContainsDecision(); // maybe not atomic but all children are
431 * Returns true iff this node contains a bound variable. This bound
432 * variable may or may not be free.
433 * @return true iff this node contains a bound variable.
438 * Convert this Node into an Expr using the currently-in-scope
439 * manager. Essentially this is like an "operator Expr()" but we
440 * don't want it to compete with implicit conversions between e.g.
441 * Node and TNode, and we want internal-to-external interface
442 * (Node -> Expr) points to be explicit. We could write an
443 * explicit Expr(Node) constructor---but that dirties the public
446 inline Expr
toExpr() const;
449 * Convert an Expr into a Node.
451 static inline Node
fromExpr(const Expr
& e
);
454 * Returns true if this node represents a constant
455 * @return true if const
457 bool isConst() const;
460 * Returns true if this node represents a constant
461 * @return true if const
463 inline bool isVar() const {
464 assertTNodeNotExpired();
465 return getMetaKind() == kind::metakind::VARIABLE
;
468 inline bool isClosure() const {
469 assertTNodeNotExpired();
470 return getKind() == kind::LAMBDA
||
471 getKind() == kind::FORALL
||
472 getKind() == kind::EXISTS
||
473 getKind() == kind::REWRITE_RULE
;
477 * Returns the unique id of this node
480 unsigned long getId() const {
481 assertTNodeNotExpired();
482 return d_nv
->getId();
486 * Returns a node representing the operator of this expression.
487 * If this is an APPLY, then the operator will be a functional term.
488 * Otherwise, it will be a node with kind BUILTIN.
490 NodeTemplate
<true> getOperator() const;
493 * Returns true if the node has an operator (i.e., it's not a
494 * variable or a constant).
496 inline bool hasOperator() const;
499 * Get the type for the node and optionally do type checking.
501 * Initial type computation will be near-constant time if
502 * type checking is not requested. Results are memoized, so that
503 * subsequent calls to getType() without type checking will be
506 * Initial type checking is linear in the size of the expression.
507 * Again, the results are memoized, so that subsequent calls to
508 * getType(), with or without type checking, will be constant
511 * NOTE: A TypeCheckingException can be thrown even when type
512 * checking is not requested. getType() will always return a
513 * valid and correct type and, thus, an exception will be thrown
514 * when no valid or correct type can be computed (e.g., if the
515 * arguments to a bit-vector operation aren't bit-vectors). When
516 * type checking is not requested, getType() will do the minimum
517 * amount of checking required to return a valid result.
519 * @param check whether we should check the type as we compute it
522 TypeNode
getType(bool check
= false) const
523 throw (CVC4::TypeCheckingExceptionPrivate
, CVC4::AssertionException
);
526 * Substitution of Nodes.
528 Node
substitute(TNode node
, TNode replacement
) const;
531 * Simultaneous substitution of Nodes. Elements in the Iterator1
532 * range will be replaced by their corresponding element in the
533 * Iterator2 range. Both ranges should have the same size.
535 template <class Iterator1
, class Iterator2
>
536 Node
substitute(Iterator1 nodesBegin
,
538 Iterator2 replacementsBegin
,
539 Iterator2 replacementsEnd
) const;
542 * Simultaneous substitution of Nodes. Iterators should be over
543 * pairs (x,y) for the rewrites [x->y].
545 template <class Iterator
>
546 Node
substitute(Iterator substitutionsBegin
,
547 Iterator substitutionsEnd
) const;
550 * Returns the kind of this node.
553 inline Kind
getKind() const {
554 assertTNodeNotExpired();
555 return Kind(d_nv
->d_kind
);
559 * Returns the metakind of this node.
560 * @return the metakind
562 inline kind::MetaKind
getMetaKind() const {
563 assertTNodeNotExpired();
564 return kind::metaKindOf(getKind());
568 * Returns the number of children this node has.
569 * @return the number of children
571 inline size_t getNumChildren() const;
574 * If this is a CONST_* Node, extract the constant from it.
577 inline const T
& getConst() const;
580 * Returns the reference count of this node.
581 * @return the refcount
583 unsigned getRefCount() const {
584 return d_nv
->getRefCount();
588 * Returns the value of the given attribute that this has been attached.
589 * @param attKind the kind of the attribute
590 * @return the value of the attribute
592 template <class AttrKind
>
593 inline typename
AttrKind::value_type
getAttribute(const AttrKind
& attKind
) const;
595 // Note that there are two, distinct hasAttribute() declarations for
596 // a reason (rather than using a pointer-valued argument with a
597 // default value): they permit more optimized code in the underlying
598 // hasAttribute() implementations.
601 * Returns true if this node has been associated an attribute of given kind.
602 * Additionaly, if a pointer to the value_kind is give, and the attribute
603 * value has been set for this node, it will be returned.
604 * @param attKind the kind of the attribute
605 * @return true if this node has the requested attribute
607 template <class AttrKind
>
608 inline bool hasAttribute(const AttrKind
& attKind
) const;
611 * Returns true if this node has been associated an attribute of given kind.
612 * Additionaly, if a pointer to the value_kind is give, and the attribute
613 * value has been set for this node, it will be returned.
614 * @param attKind the kind of the attribute
615 * @param value where to store the value if it exists
616 * @return true if this node has the requested attribute
618 template <class AttrKind
>
619 inline bool getAttribute(const AttrKind
& attKind
,
620 typename
AttrKind::value_type
& value
) const;
623 * Sets the given attribute of this node to the given value.
624 * @param attKind the kind of the atribute
625 * @param value the value to set the attribute to
627 template <class AttrKind
>
628 inline void setAttribute(const AttrKind
& attKind
,
629 const typename
AttrKind::value_type
& value
);
631 /** Iterator allowing for scanning through the children. */
632 typedef typename
expr::NodeValue::iterator
< NodeTemplate
<ref_count
> > iterator
;
633 /** Constant iterator allowing for scanning through the children. */
634 typedef typename
expr::NodeValue::iterator
< NodeTemplate
<ref_count
> > const_iterator
;
636 class kinded_iterator
{
637 friend class NodeTemplate
<ref_count
>;
639 NodeTemplate
<ref_count
> d_node
;
642 kinded_iterator(TNode node
, ssize_t child
) :
647 // These are factories to serve as clients to Node::begin<K>() and
649 static kinded_iterator
begin(TNode n
, Kind k
) {
650 return kinded_iterator(n
, n
.getKind() == k
? 0 : -2);
652 static kinded_iterator
end(TNode n
, Kind k
) {
653 return kinded_iterator(n
, n
.getKind() == k
? n
.getNumChildren() : -1);
657 typedef NodeTemplate
<ref_count
> value_type
;
658 typedef std::ptrdiff_t difference_type
;
659 typedef NodeTemplate
<ref_count
>* pointer
;
660 typedef NodeTemplate
<ref_count
>& reference
;
663 d_node(NodeTemplate
<ref_count
>::null()),
667 kinded_iterator(const kinded_iterator
& i
) :
672 NodeTemplate
<ref_count
> operator*() {
673 return d_child
< 0 ? d_node
: d_node
[d_child
];
676 bool operator==(const kinded_iterator
& i
) {
677 return d_node
== i
.d_node
&& d_child
== i
.d_child
;
680 bool operator!=(const kinded_iterator
& i
) {
681 return !(*this == i
);
684 kinded_iterator
& operator++() {
691 kinded_iterator
operator++(int) {
692 kinded_iterator i
= *this;
696 };/* class NodeTemplate<ref_count>::kinded_iterator */
698 typedef kinded_iterator const_kinded_iterator
;
701 * Returns the iterator pointing to the first child.
702 * @return the iterator
704 inline iterator
begin() {
705 assertTNodeNotExpired();
706 return d_nv
->begin
< NodeTemplate
<ref_count
> >();
710 * Returns the iterator pointing to the end of the children (one beyond the
712 * @return the end of the children iterator.
714 inline iterator
end() {
715 assertTNodeNotExpired();
716 return d_nv
->end
< NodeTemplate
<ref_count
> >();
720 * Returns the iterator pointing to the first child, if the node's
721 * kind is the same as the parameter, otherwise returns the iterator
722 * pointing to the node itself. This is useful if you want to
723 * pretend to iterate over a "unary" PLUS, for instance, since unary
724 * PLUSes don't exist---begin(PLUS) will give an iterator over the
725 * children if the node's a PLUS node, otherwise give an iterator
726 * over the node itself, as if it were a unary PLUS.
727 * @param kind the kind to match
728 * @return the kinded_iterator iterating over this Node (if its kind
729 * is not the passed kind) or its children
731 inline kinded_iterator
begin(Kind kind
) {
732 assertTNodeNotExpired();
733 return kinded_iterator::begin(*this, kind
);
737 * Returns the iterator pointing to the end of the children (one
738 * beyond the last one), if the node's kind is the same as the
739 * parameter, otherwise returns the iterator pointing to the
740 * one-of-the-node-itself. This is useful if you want to pretend to
741 * iterate over a "unary" PLUS, for instance, since unary PLUSes
742 * don't exist---begin(PLUS) will give an iterator over the children
743 * if the node's a PLUS node, otherwise give an iterator over the
744 * node itself, as if it were a unary PLUS.
745 * @param kind the kind to match
746 * @return the kinded_iterator pointing off-the-end of this Node (if
747 * its kind is not the passed kind) or off-the-end of its children
749 inline kinded_iterator
end(Kind kind
) {
750 assertTNodeNotExpired();
751 return kinded_iterator::end(*this, kind
);
755 * Returns the const_iterator pointing to the first child.
756 * @return the const_iterator
758 inline const_iterator
begin() const {
759 assertTNodeNotExpired();
760 return d_nv
->begin
< NodeTemplate
<ref_count
> >();
764 * Returns the const_iterator pointing to the end of the children (one
765 * beyond the last one.
766 * @return the end of the children const_iterator.
768 inline const_iterator
end() const {
769 assertTNodeNotExpired();
770 return d_nv
->end
< NodeTemplate
<ref_count
> >();
774 * Returns the iterator pointing to the first child, if the node's
775 * kind is the same as the parameter, otherwise returns the iterator
776 * pointing to the node itself. This is useful if you want to
777 * pretend to iterate over a "unary" PLUS, for instance, since unary
778 * PLUSes don't exist---begin(PLUS) will give an iterator over the
779 * children if the node's a PLUS node, otherwise give an iterator
780 * over the node itself, as if it were a unary PLUS.
781 * @param kind the kind to match
782 * @return the kinded_iterator iterating over this Node (if its kind
783 * is not the passed kind) or its children
785 inline const_kinded_iterator
begin(Kind kind
) const {
786 assertTNodeNotExpired();
787 return const_kinded_iterator::begin(*this, kind
);
791 * Returns the iterator pointing to the end of the children (one
792 * beyond the last one), if the node's kind is the same as the
793 * parameter, otherwise returns the iterator pointing to the
794 * one-of-the-node-itself. This is useful if you want to pretend to
795 * iterate over a "unary" PLUS, for instance, since unary PLUSes
796 * don't exist---begin(PLUS) will give an iterator over the children
797 * if the node's a PLUS node, otherwise give an iterator over the
798 * node itself, as if it were a unary PLUS.
799 * @param kind the kind to match
800 * @return the kinded_iterator pointing off-the-end of this Node (if
801 * its kind is not the passed kind) or off-the-end of its children
803 inline const_kinded_iterator
end(Kind kind
) const {
804 assertTNodeNotExpired();
805 return const_kinded_iterator::end(*this, kind
);
809 * Converts this node into a string representation.
810 * @return the string representation of this node.
812 inline std::string
toString() const {
813 assertTNodeNotExpired();
814 return d_nv
->toString();
818 * Converts this node into a string representation and sends it to the
821 * @param out the stream to serialize this node to
822 * @param toDepth the depth to which to print this expression, or -1 to
824 * @param types set to true to ascribe types to the output expressions
825 * (might break language compliance, but good for debugging expressions)
826 * @param language the language in which to output
828 inline void toStream(std::ostream
& out
, int toDepth
= -1, bool types
= false, size_t dag
= 1,
829 OutputLanguage language
= language::output::LANG_AUTO
) const {
830 assertTNodeNotExpired();
831 d_nv
->toStream(out
, toDepth
, types
, dag
, language
);
835 * IOStream manipulator to set the maximum depth of Nodes when
836 * pretty-printing. -1 means print to any depth. E.g.:
838 * // let a, b, c, and d be VARIABLEs
839 * Node n = nm->mkNode(OR, a, b, nm->mkNode(AND, c, nm->mkNode(NOT, d)))
840 * out << setdepth(3) << n;
842 * gives "(OR a b (AND c (NOT d)))", but
844 * out << setdepth(1) << [same node as above]
846 * gives "(OR a b (...))"
848 typedef expr::ExprSetDepth setdepth
;
851 * IOStream manipulator to print type ascriptions or not.
853 * // let a, b, c, and d be variables of sort U
854 * Node n = nm->mkNode(OR, a, b, nm->mkNode(AND, c, nm->mkNode(NOT, d)))
857 * gives "(OR a:U b:U (AND c:U (NOT d:U)))", but
859 typedef expr::ExprPrintTypes printtypes
;
862 * IOStream manipulator to print expressions as DAGs (or not).
864 typedef expr::ExprDag dag
;
867 * IOStream manipulator to set the output language for Exprs.
869 typedef language::SetLanguage setlanguage
;
872 * Very basic pretty printer for Node.
873 * @param out output stream to print to.
874 * @param indent number of spaces to indent the formula by.
876 inline void printAst(std::ostream
& out
, int indent
= 0) const;
879 * Check if the node has a subterm t.
881 inline bool hasSubterm(NodeTemplate
<false> t
, bool strict
= false) const;
883 template <bool ref_count2
>
884 NodeTemplate
<true> eqNode(const NodeTemplate
<ref_count2
>& right
) const;
886 NodeTemplate
<true> notNode() const;
887 NodeTemplate
<true> negate() const;
888 template <bool ref_count2
>
889 NodeTemplate
<true> andNode(const NodeTemplate
<ref_count2
>& right
) const;
890 template <bool ref_count2
>
891 NodeTemplate
<true> orNode(const NodeTemplate
<ref_count2
>& right
) const;
892 template <bool ref_count2
, bool ref_count3
>
893 NodeTemplate
<true> iteNode(const NodeTemplate
<ref_count2
>& thenpart
,
894 const NodeTemplate
<ref_count3
>& elsepart
) const;
895 template <bool ref_count2
>
896 NodeTemplate
<true> iffNode(const NodeTemplate
<ref_count2
>& right
) const;
897 template <bool ref_count2
>
898 NodeTemplate
<true> impNode(const NodeTemplate
<ref_count2
>& right
) const;
899 template <bool ref_count2
>
900 NodeTemplate
<true> xorNode(const NodeTemplate
<ref_count2
>& right
) const;
902 };/* class NodeTemplate<ref_count> */
905 * Serializes a given node to the given stream.
907 * @param out the output stream to use
908 * @param n the node to output to the stream
911 inline std::ostream
& operator<<(std::ostream
& out
, TNode n
) {
913 Node::setdepth::getDepth(out
),
914 Node::printtypes::getPrintTypes(out
),
915 Node::dag::getDag(out
),
916 Node::setlanguage::getLanguage(out
));
921 * Serializes a vector of node to the given stream.
923 * @param out the output stream to use
924 * @param ns the vector of nodes to output to the stream
927 template<bool ref_count
>
928 inline std::ostream
& operator<<(std::ostream
& out
,
929 const std::vector
< NodeTemplate
<ref_count
> > & ns
) {
930 for(typename
std::vector
< NodeTemplate
<ref_count
> >::const_iterator
931 i
=ns
.begin(), end
=ns
.end();
939 }/* CVC4 namespace */
941 #include <ext/hash_map>
943 //#include "expr/attribute.h"
944 #include "expr/node_manager.h"
945 #include "expr/type_checker.h"
949 inline size_t NodeHashFunction::operator()(Node node
) const {
952 inline size_t TNodeHashFunction::operator()(TNode node
) const {
956 struct TNodePairHashFunction
{
957 size_t operator()(const std::pair
<CVC4::TNode
, CVC4::TNode
>& pair
) const {
958 TNode n1
= pair
.first
;
959 TNode n2
= pair
.second
;
961 return (size_t) (n1
.getId() * 0x9e3779b9 + n2
.getId());
963 };/* struct TNodePairHashFunction */
965 template <bool ref_count
>
966 inline size_t NodeTemplate
<ref_count
>::getNumChildren() const {
967 assertTNodeNotExpired();
968 return d_nv
->getNumChildren();
971 template <bool ref_count
>
973 inline const T
& NodeTemplate
<ref_count
>::getConst() const {
974 assertTNodeNotExpired();
975 return d_nv
->getConst
<T
>();
978 template <bool ref_count
>
979 template <class AttrKind
>
980 inline typename
AttrKind::value_type NodeTemplate
<ref_count
>::
981 getAttribute(const AttrKind
&) const {
982 Assert( NodeManager::currentNM() != NULL
,
983 "There is no current CVC4::NodeManager associated to this thread.\n"
984 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
986 assertTNodeNotExpired();
988 return NodeManager::currentNM()->getAttribute(*this, AttrKind());
991 template <bool ref_count
>
992 template <class AttrKind
>
993 inline bool NodeTemplate
<ref_count
>::
994 hasAttribute(const AttrKind
&) const {
995 Assert( NodeManager::currentNM() != NULL
,
996 "There is no current CVC4::NodeManager associated to this thread.\n"
997 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
999 assertTNodeNotExpired();
1001 return NodeManager::currentNM()->hasAttribute(*this, AttrKind());
1004 template <bool ref_count
>
1005 template <class AttrKind
>
1006 inline bool NodeTemplate
<ref_count
>::getAttribute(const AttrKind
&,
1007 typename
AttrKind::value_type
& ret
) const {
1008 Assert( NodeManager::currentNM() != NULL
,
1009 "There is no current CVC4::NodeManager associated to this thread.\n"
1010 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
1012 assertTNodeNotExpired();
1014 return NodeManager::currentNM()->getAttribute(*this, AttrKind(), ret
);
1017 template <bool ref_count
>
1018 template <class AttrKind
>
1019 inline void NodeTemplate
<ref_count
>::
1020 setAttribute(const AttrKind
&, const typename
AttrKind::value_type
& value
) {
1021 Assert( NodeManager::currentNM() != NULL
,
1022 "There is no current CVC4::NodeManager associated to this thread.\n"
1023 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
1025 assertTNodeNotExpired();
1027 NodeManager::currentNM()->setAttribute(*this, AttrKind(), value
);
1030 template <bool ref_count
>
1031 NodeTemplate
<ref_count
> NodeTemplate
<ref_count
>::s_null(&expr::NodeValue::null());
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 NodeTemplate
<ref_count
>::NodeTemplate(const expr::NodeValue
* ev
) :
1039 d_nv(const_cast<expr::NodeValue
*> (ev
)) {
1040 Assert(d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1044 Assert(d_nv
->d_rc
> 0 || d_nv
== &expr::NodeValue::null(),
1045 "TNode constructed from NodeValue with rc == 0");
1049 // the code for these two following constructors ("conversion/copy
1050 // constructors") is identical, but we need both. see comment in the
1053 template <bool ref_count
>
1054 NodeTemplate
<ref_count
>::NodeTemplate(const NodeTemplate
<!ref_count
>& e
) {
1055 Assert(e
.d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1058 Assert(d_nv
->d_rc
> 0, "Node constructed from TNode with rc == 0");
1061 // shouldn't ever fail
1062 Assert(d_nv
->d_rc
> 0, "TNode constructed from Node with rc == 0");
1066 template <bool ref_count
>
1067 NodeTemplate
<ref_count
>::NodeTemplate(const NodeTemplate
& e
) {
1068 Assert(e
.d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1071 // shouldn't ever fail
1072 Assert(d_nv
->d_rc
> 0, "Node constructed from Node with rc == 0");
1075 Assert(d_nv
->d_rc
> 0, "TNode constructed from TNode with rc == 0");
1079 template <bool ref_count
>
1080 NodeTemplate
<ref_count
>::NodeTemplate(const Expr
& e
) {
1081 Assert(e
.d_node
!= NULL
, "Expecting a non-NULL expression value!");
1082 Assert(e
.d_node
->d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1083 d_nv
= e
.d_node
->d_nv
;
1084 // shouldn't ever fail
1085 Assert(d_nv
->d_rc
> 0, "Node constructed from Expr with rc == 0");
1091 template <bool ref_count
>
1092 NodeTemplate
<ref_count
>::~NodeTemplate() throw(AssertionException
) {
1093 Assert(d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1095 // shouldn't ever fail
1096 Assert(d_nv
->d_rc
> 0, "Node reference count would be negative");
1101 template <bool ref_count
>
1102 void NodeTemplate
<ref_count
>::assignNodeValue(expr::NodeValue
* ev
) {
1107 Assert(d_nv
->d_rc
> 0, "TNode assigned to NodeValue with rc == 0");
1111 template <bool ref_count
>
1112 NodeTemplate
<ref_count
>& NodeTemplate
<ref_count
>::
1113 operator=(const NodeTemplate
& e
) {
1114 Assert(d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1115 Assert(e
.d_nv
!= NULL
, "Expecting a non-NULL expression value on RHS!");
1116 if(__builtin_expect( ( d_nv
!= e
.d_nv
), true )) {
1118 // shouldn't ever fail
1119 Assert(d_nv
->d_rc
> 0,
1120 "Node reference count would be negative");
1125 // shouldn't ever fail
1126 Assert(d_nv
->d_rc
> 0, "Node assigned from Node with rc == 0");
1129 Assert(d_nv
->d_rc
> 0, "TNode assigned from TNode with rc == 0");
1135 template <bool ref_count
>
1136 NodeTemplate
<ref_count
>& NodeTemplate
<ref_count
>::
1137 operator=(const NodeTemplate
<!ref_count
>& e
) {
1138 Assert(d_nv
!= NULL
, "Expecting a non-NULL expression value!");
1139 Assert(e
.d_nv
!= NULL
, "Expecting a non-NULL expression value on RHS!");
1140 if(__builtin_expect( ( d_nv
!= e
.d_nv
), true )) {
1142 // shouldn't ever fail
1143 Assert(d_nv
->d_rc
> 0, "Node reference count would be negative");
1148 Assert(d_nv
->d_rc
> 0, "Node assigned from TNode with rc == 0");
1151 // shouldn't ever happen
1152 Assert(d_nv
->d_rc
> 0, "TNode assigned from Node with rc == 0");
1158 template <bool ref_count
>
1159 template <bool ref_count2
>
1161 NodeTemplate
<ref_count
>::eqNode(const NodeTemplate
<ref_count2
>& right
) const {
1162 assertTNodeNotExpired();
1163 return NodeManager::currentNM()->mkNode(kind::EQUAL
, *this, right
);
1166 template <bool ref_count
>
1167 NodeTemplate
<true> NodeTemplate
<ref_count
>::notNode() const {
1168 assertTNodeNotExpired();
1169 return NodeManager::currentNM()->mkNode(kind::NOT
, *this);
1172 template <bool ref_count
>
1173 NodeTemplate
<true> NodeTemplate
<ref_count
>::negate() const {
1174 assertTNodeNotExpired();
1175 return (getKind() == kind::NOT
) ? NodeTemplate
<true>(d_nv
->getChild(0)) : NodeManager::currentNM()->mkNode(kind::NOT
, *this);
1178 template <bool ref_count
>
1179 template <bool ref_count2
>
1181 NodeTemplate
<ref_count
>::andNode(const NodeTemplate
<ref_count2
>& right
) const {
1182 assertTNodeNotExpired();
1183 return NodeManager::currentNM()->mkNode(kind::AND
, *this, right
);
1186 template <bool ref_count
>
1187 template <bool ref_count2
>
1189 NodeTemplate
<ref_count
>::orNode(const NodeTemplate
<ref_count2
>& right
) const {
1190 assertTNodeNotExpired();
1191 return NodeManager::currentNM()->mkNode(kind::OR
, *this, right
);
1194 template <bool ref_count
>
1195 template <bool ref_count2
, bool ref_count3
>
1197 NodeTemplate
<ref_count
>::iteNode(const NodeTemplate
<ref_count2
>& thenpart
,
1198 const NodeTemplate
<ref_count3
>& elsepart
) const {
1199 assertTNodeNotExpired();
1200 return NodeManager::currentNM()->mkNode(kind::ITE
, *this, thenpart
, elsepart
);
1203 template <bool ref_count
>
1204 template <bool ref_count2
>
1206 NodeTemplate
<ref_count
>::iffNode(const NodeTemplate
<ref_count2
>& right
) const {
1207 assertTNodeNotExpired();
1208 return NodeManager::currentNM()->mkNode(kind::IFF
, *this, right
);
1211 template <bool ref_count
>
1212 template <bool ref_count2
>
1214 NodeTemplate
<ref_count
>::impNode(const NodeTemplate
<ref_count2
>& right
) const {
1215 assertTNodeNotExpired();
1216 return NodeManager::currentNM()->mkNode(kind::IMPLIES
, *this, right
);
1219 template <bool ref_count
>
1220 template <bool ref_count2
>
1222 NodeTemplate
<ref_count
>::xorNode(const NodeTemplate
<ref_count2
>& right
) const {
1223 assertTNodeNotExpired();
1224 return NodeManager::currentNM()->mkNode(kind::XOR
, *this, right
);
1227 template <bool ref_count
>
1229 NodeTemplate
<ref_count
>::printAst(std::ostream
& out
, int indent
) const {
1230 assertTNodeNotExpired();
1231 d_nv
->printAst(out
, indent
);
1235 * Returns a node representing the operator of this expression.
1236 * If this is an APPLY, then the operator will be a functional term.
1237 * Otherwise, it will be a node with kind BUILTIN.
1239 template <bool ref_count
>
1240 NodeTemplate
<true> NodeTemplate
<ref_count
>::getOperator() const {
1241 Assert( NodeManager::currentNM() != NULL
,
1242 "There is no current CVC4::NodeManager associated to this thread.\n"
1243 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
1245 assertTNodeNotExpired();
1247 switch(kind::MetaKind mk
= getMetaKind()) {
1248 case kind::metakind::INVALID
:
1249 IllegalArgument(*this, "getOperator() called on Node with INVALID-kinded kind");
1251 case kind::metakind::VARIABLE
:
1252 IllegalArgument(*this, "getOperator() called on Node with VARIABLE-kinded kind");
1254 case kind::metakind::OPERATOR
: {
1255 /* Returns a BUILTIN node. */
1256 return NodeManager::currentNM()->operatorOf(getKind());
1259 case kind::metakind::PARAMETERIZED
:
1260 /* The operator is the first child. */
1261 return Node(d_nv
->d_children
[0]);
1263 case kind::metakind::CONSTANT
:
1264 IllegalArgument(*this, "getOperator() called on Node with CONSTANT-kinded kind");
1272 * Returns true if the node has an operator (i.e., it's not a variable
1275 template <bool ref_count
>
1276 inline bool NodeTemplate
<ref_count
>::hasOperator() const {
1277 assertTNodeNotExpired();
1278 return NodeManager::hasOperator(getKind());
1281 template <bool ref_count
>
1282 TypeNode NodeTemplate
<ref_count
>::getType(bool check
) const
1283 throw (CVC4::TypeCheckingExceptionPrivate
, CVC4::AssertionException
) {
1284 Assert( NodeManager::currentNM() != NULL
,
1285 "There is no current CVC4::NodeManager associated to this thread.\n"
1286 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
1288 assertTNodeNotExpired();
1290 return NodeManager::currentNM()->getType(*this, check
);
1293 template <bool ref_count
>
1295 NodeTemplate
<ref_count
>::substitute(TNode node
, TNode replacement
) const {
1296 if (node
== *this) {
1299 std::hash_map
<TNode
, TNode
, TNodeHashFunction
> cache
;
1300 return substitute(node
, replacement
, cache
);
1303 template <bool ref_count
>
1305 NodeTemplate
<ref_count
>::substitute(TNode node
, TNode replacement
,
1306 std::hash_map
<TNode
, TNode
, TNodeHashFunction
>& cache
) const {
1307 Assert(node
!= *this);
1309 if (getNumChildren() == 0) {
1314 typename
std::hash_map
<TNode
, TNode
, TNodeHashFunction
>::const_iterator i
= cache
.find(*this);
1315 if(i
!= cache
.end()) {
1319 // otherwise compute
1320 NodeBuilder
<> nb(getKind());
1321 if(getMetaKind() == kind::metakind::PARAMETERIZED
) {
1322 // push the operator
1323 if(getOperator() == node
) {
1326 nb
<< getOperator().substitute(node
, replacement
, cache
);
1329 for(const_iterator i
= begin(),
1336 nb
<< (*i
).substitute(node
, replacement
, cache
);
1347 template <bool ref_count
>
1348 template <class Iterator1
, class Iterator2
>
1350 NodeTemplate
<ref_count
>::substitute(Iterator1 nodesBegin
,
1352 Iterator2 replacementsBegin
,
1353 Iterator2 replacementsEnd
) const {
1354 std::hash_map
<TNode
, TNode
, TNodeHashFunction
> cache
;
1355 return substitute(nodesBegin
, nodesEnd
,
1356 replacementsBegin
, replacementsEnd
, cache
);
1359 template <bool ref_count
>
1360 template <class Iterator1
, class Iterator2
>
1362 NodeTemplate
<ref_count
>::substitute(Iterator1 nodesBegin
,
1364 Iterator2 replacementsBegin
,
1365 Iterator2 replacementsEnd
,
1366 std::hash_map
<TNode
, TNode
, TNodeHashFunction
>& cache
) const {
1368 typename
std::hash_map
<TNode
, TNode
, TNodeHashFunction
>::const_iterator i
= cache
.find(*this);
1369 if(i
!= cache
.end()) {
1373 // otherwise compute
1374 Assert( std::distance(nodesBegin
, nodesEnd
) == std::distance(replacementsBegin
, replacementsEnd
),
1375 "Substitution iterator ranges must be equal size" );
1376 Iterator1 j
= find(nodesBegin
, nodesEnd
, TNode(*this));
1378 Iterator2 b
= replacementsBegin
;
1379 std::advance(b
, std::distance(nodesBegin
, j
));
1383 } else if(getNumChildren() == 0) {
1384 cache
[*this] = *this;
1387 NodeBuilder
<> nb(getKind());
1388 if(getMetaKind() == kind::metakind::PARAMETERIZED
) {
1389 // push the operator
1390 nb
<< getOperator().substitute(nodesBegin
, nodesEnd
,
1391 replacementsBegin
, replacementsEnd
,
1394 for(const_iterator i
= begin(),
1398 nb
<< (*i
).substitute(nodesBegin
, nodesEnd
,
1399 replacementsBegin
, replacementsEnd
,
1408 template <bool ref_count
>
1409 template <class Iterator
>
1411 NodeTemplate
<ref_count
>::substitute(Iterator substitutionsBegin
,
1412 Iterator substitutionsEnd
) const {
1413 std::hash_map
<TNode
, TNode
, TNodeHashFunction
> cache
;
1414 return substitute(substitutionsBegin
, substitutionsEnd
, cache
);
1417 template <bool ref_count
>
1418 template <class Iterator
>
1420 NodeTemplate
<ref_count
>::substitute(Iterator substitutionsBegin
,
1421 Iterator substitutionsEnd
,
1422 std::hash_map
<TNode
, TNode
, TNodeHashFunction
>& cache
) const {
1424 typename
std::hash_map
<TNode
, TNode
, TNodeHashFunction
>::const_iterator i
= cache
.find(*this);
1425 if(i
!= cache
.end()) {
1429 // otherwise compute
1430 Iterator j
= find_if(substitutionsBegin
, substitutionsEnd
,
1431 bind2nd(first_equal_to
<typename
Iterator::value_type::first_type
, typename
Iterator::value_type::second_type
>(), *this));
1432 if(j
!= substitutionsEnd
) {
1433 Node n
= (*j
).second
;
1436 } else if(getNumChildren() == 0) {
1437 cache
[*this] = *this;
1440 NodeBuilder
<> nb(getKind());
1441 if(getMetaKind() == kind::metakind::PARAMETERIZED
) {
1442 // push the operator
1443 nb
<< getOperator().substitute(substitutionsBegin
, substitutionsEnd
, cache
);
1445 for(const_iterator i
= begin(),
1449 nb
<< (*i
).substitute(substitutionsBegin
, substitutionsEnd
, cache
);
1457 template <bool ref_count
>
1458 inline Expr NodeTemplate
<ref_count
>::toExpr() const {
1459 assertTNodeNotExpired();
1460 return NodeManager::currentNM()->toExpr(*this);
1463 // intentionally not defined for TNode
1465 inline Node NodeTemplate
<true>::fromExpr(const Expr
& e
) {
1466 return NodeManager::fromExpr(e
);
1469 template<bool ref_count
>
1470 bool NodeTemplate
<ref_count
>::hasSubterm(NodeTemplate
<false> t
, bool strict
) const {
1471 typedef std::hash_set
<TNode
, TNodeHashFunction
> node_set
;
1473 if (!strict
&& *this == t
) {
1478 std::vector
<TNode
> toProcess
;
1480 toProcess
.push_back(*this);
1482 for (unsigned i
= 0; i
< toProcess
.size(); ++ i
) {
1483 TNode current
= toProcess
[i
];
1484 for(unsigned j
= 0, j_end
= current
.getNumChildren(); j
< j_end
; ++ j
) {
1485 TNode child
= current
[j
];
1489 if (visited
.find(child
) != visited
.end()) {
1492 visited
.insert(child
);
1493 toProcess
.push_back(child
);
1503 * Pretty printer for use within gdb. This is not intended to be used
1504 * outside of gdb. This writes to the Warning() stream and immediately
1505 * flushes the stream.
1507 * Note that this function cannot be a template, since the compiler
1508 * won't instantiate it. Even if we explicitly instantiate. (Odd?)
1509 * So we implement twice. We mark as __attribute__((used)) so that
1510 * GCC emits code for it even though static analysis indicates it's
1513 * Tim's Note: I moved this into the node.h file because this allows gdb
1514 * to find the symbol, and use it, which is the first standard this code needs
1515 * to meet. A cleaner solution is welcomed.
1517 static void __attribute__((used
)) debugPrintNode(const NodeTemplate
<true>& n
) {
1518 Warning() << Node::setdepth(-1)
1519 << Node::printtypes(false)
1521 << Node::setlanguage(language::output::LANG_AST
)
1525 static void __attribute__((used
)) debugPrintNodeNoDag(const NodeTemplate
<true>& n
) {
1526 Warning() << Node::setdepth(-1)
1527 << Node::printtypes(false)
1529 << Node::setlanguage(language::output::LANG_AST
)
1533 static void __attribute__((used
)) debugPrintRawNode(const NodeTemplate
<true>& n
) {
1534 n
.printAst(Warning(), 0);
1538 static void __attribute__((used
)) debugPrintTNode(const NodeTemplate
<false>& n
) {
1539 Warning() << Node::setdepth(-1)
1540 << Node::printtypes(false)
1542 << Node::setlanguage(language::output::LANG_AST
)
1546 static void __attribute__((used
)) debugPrintTNodeNoDag(const NodeTemplate
<false>& n
) {
1547 Warning() << Node::setdepth(-1)
1548 << Node::printtypes(false)
1550 << Node::setlanguage(language::output::LANG_AST
)
1554 static void __attribute__((used
)) debugPrintRawTNode(const NodeTemplate
<false>& n
) {
1555 n
.printAst(Warning(), 0);
1558 #endif /* CVC4_DEBUG */
1560 }/* CVC4 namespace */
1562 #endif /* __CVC4__NODE_H */