1 /********************* */
2 /*! \file node_manager.h
4 ** Top contributors (to current version):
5 ** Morgan Deters, Christopher L. Conway, Dejan Jovanovic
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2017 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.\endverbatim
12 ** \brief A manager for Nodes
14 ** A manager for Nodes.
16 ** Reviewed by Chris Conway, Apr 5 2010 (bug #65).
19 #include "cvc4_private.h"
21 /* circular dependency; force node.h first */
22 //#include "expr/attribute.h"
23 #include "expr/node.h"
24 #include "expr/type_node.h"
25 #include "expr/expr.h"
26 #include "expr/expr_manager.h"
28 #ifndef __CVC4__NODE_MANAGER_H
29 #define __CVC4__NODE_MANAGER_H
33 #include <ext/hash_set>
36 #include "expr/kind.h"
37 #include "expr/metakind.h"
38 #include "expr/node_value.h"
39 #include "util/subrange_bound.h"
40 #include "options/options.h"
44 class StatisticsRegistry
;
45 class ResourceManager
;
49 class AttributeUniqueId
;
50 class AttributeManager
;
51 }/* CVC4::expr::attr namespace */
54 }/* CVC4::expr namespace */
57 * An interface that an interested party can implement and then subscribe
58 * to NodeManager events via NodeManager::subscribeEvents(this).
60 class NodeManagerListener
{
62 virtual ~NodeManagerListener() {}
63 virtual void nmNotifyNewSort(TypeNode tn
, uint32_t flags
) {}
64 virtual void nmNotifyNewSortConstructor(TypeNode tn
) {}
65 virtual void nmNotifyInstantiateSortConstructor(TypeNode ctor
, TypeNode sort
,
67 virtual void nmNotifyNewDatatypes(
68 const std::vector
<DatatypeType
>& datatypes
) {}
69 virtual void nmNotifyNewVar(TNode n
, uint32_t flags
) {}
70 virtual void nmNotifyNewSkolem(TNode n
, const std::string
& comment
,
73 * Notify a listener of a Node that's being GCed. If this function stores a
75 * to the Node somewhere, very bad things will happen.
77 virtual void nmNotifyDeleteNode(TNode n
) {}
78 }; /* class NodeManagerListener */
81 template <unsigned nchild_thresh
> friend class CVC4::NodeBuilder
;
82 friend class NodeManagerScope
;
83 friend class expr::NodeValue
;
84 friend class expr::TypeChecker
;
86 // friends so they can access mkVar() here, which is private
87 friend Expr
ExprManager::mkVar(const std::string
&, Type
, uint32_t flags
);
88 friend Expr
ExprManager::mkVar(Type
, uint32_t flags
);
90 // friend so it can access NodeManager's d_listeners and notify clients
91 friend std::vector
<DatatypeType
> ExprManager::mkMutualDatatypeTypes(std::vector
<Datatype
>&, std::set
<Type
>&);
93 /** Predicate for use with STL algorithms */
94 struct NodeValueReferenceCountNonZero
{
95 bool operator()(expr::NodeValue
* nv
) { return nv
->d_rc
> 0; }
98 typedef __gnu_cxx::hash_set
<expr::NodeValue
*,
99 expr::NodeValuePoolHashFunction
,
100 expr::NodeValuePoolEq
> NodeValuePool
;
101 typedef __gnu_cxx::hash_set
<expr::NodeValue
*,
102 expr::NodeValueIDHashFunction
,
103 expr::NodeValueIDEquality
> NodeValueIDSet
;
105 static CVC4_THREADLOCAL(NodeManager
*) s_current
;
108 StatisticsRegistry
* d_statisticsRegistry
;
110 ResourceManager
* d_resourceManager
;
113 * A list of registrations on d_options to that call into d_resourceManager.
114 * These must be garbage collected before d_options and d_resourceManager.
116 ListenerRegistrationList
* d_registrations
;
118 NodeValuePool d_nodeValuePool
;
122 expr::attr::AttributeManager
* d_attrManager
;
124 /** The associated ExprManager */
125 ExprManager
* d_exprManager
;
128 * The node value we're currently freeing. This unique node value
129 * is permitted to have outstanding TNodes to it (in "soft"
130 * contexts, like as a key in attribute tables), even though
131 * normally it's an error to have a TNode to a node value with a
132 * reference count of 0. Being "under deletion" also enables
133 * assertions that inc() is not called on it. (A poorly-behaving
134 * attribute cleanup function could otherwise create a "Node" that
135 * points to the node value that is in the process of being deleted,
136 * springing it back to life.)
138 expr::NodeValue
* d_nodeUnderDeletion
;
141 * True iff we are in reclaimZombies(). This avoids unnecessary
142 * recursion; a NodeValue being deleted might zombify other
143 * NodeValues, but these shouldn't trigger a (recursive) call to
146 bool d_inReclaimZombies
;
149 * The set of zombie nodes. We may want to revisit this design, as
150 * we might like to delete nodes in least-recently-used order. But
151 * we also need to avoid processing a zombie twice.
153 NodeValueIDSet d_zombies
;
156 * NodeValues with maxed out reference counts. These live as long as the
157 * NodeManager. They have a custom deallocation procedure at the very end.
159 std::vector
<expr::NodeValue
*> d_maxedOut
;
162 * A set of operator singletons (w.r.t. to this NodeManager
163 * instance) for operators. Conceptually, Nodes with kind, say,
164 * PLUS, are APPLYs of a PLUS operator to arguments. This array
165 * holds the set of operators for these things. A PLUS operator is
166 * a Node with kind "BUILTIN", and if you call
167 * plusOperator->getConst<CVC4::Kind>(), you get kind::PLUS back.
169 Node d_operators
[kind::LAST_KIND
];
171 /** unique vars per (Kind,Type) */
172 std::map
< Kind
, std::map
< TypeNode
, Node
> > d_unique_vars
;
175 * A list of subscribers for NodeManager events.
177 std::vector
<NodeManagerListener
*> d_listeners
;
179 /** A list of datatypes owned by this node manager. */
180 std::vector
<Datatype
*> d_ownedDatatypes
;
183 * A map of tuple and record types to their corresponding datatype.
185 class TupleTypeCache
{
187 std::map
< TypeNode
, TupleTypeCache
> d_children
;
189 TypeNode
getTupleType( NodeManager
* nm
, std::vector
< TypeNode
>& types
, unsigned index
= 0 );
193 std::map
< TypeNode
, std::map
< std::string
, RecTypeCache
> > d_children
;
195 TypeNode
getRecordType( NodeManager
* nm
, const Record
& rec
, unsigned index
= 0 );
197 TupleTypeCache d_tt_cache
;
198 RecTypeCache d_rt_cache
;
201 * Keep a count of all abstract values produced by this NodeManager.
202 * Abstract values have a type attribute, so if multiple SmtEngines
203 * are attached to this NodeManager, we don't want their abstract
206 unsigned d_abstractValueCount
;
209 * A counter used to produce unique skolem names.
211 * Note that it is NOT incremented when skolems are created using
212 * SKOLEM_EXACT_NAME, so it is NOT a count of the skolems produced
213 * by this node manager.
215 unsigned d_skolemCounter
;
218 * Look up a NodeValue in the pool associated to this NodeManager.
219 * The NodeValue argument need not be a "completely-constructed"
220 * NodeValue. In particular, "non-inlined" constants are permitted
223 * For non-CONSTANT metakinds, nv's d_kind and d_nchildren should be
224 * correctly set, and d_children[0..n-1] should be valid (extant)
225 * NodeValues for lookup.
227 * For CONSTANT metakinds, nv's d_kind should be set correctly.
228 * Normally a CONSTANT would have d_nchildren == 0 and the constant
229 * value inlined in the d_children space. However, here we permit
230 * "non-inlined" NodeValues to avoid unnecessary copying. For
231 * these, d_nchildren == 1, and d_nchildren is a pointer to the
234 * The point of this complex design is to permit efficient lookups
235 * (without fully constructing a NodeValue). In the case that the
236 * argument is not fully constructed, and this function returns
237 * NULL, the caller should fully construct an equivalent one before
238 * calling poolInsert(). NON-FULLY-CONSTRUCTED NODEVALUES are not
239 * permitted in the pool!
241 inline expr::NodeValue
* poolLookup(expr::NodeValue
* nv
) const;
244 * Insert a NodeValue into the NodeManager's pool.
246 * It is an error to insert a NodeValue already in the pool.
247 * Enquire first with poolLookup().
249 inline void poolInsert(expr::NodeValue
* nv
);
252 * Remove a NodeValue from the NodeManager's pool.
254 * It is an error to request the removal of a NodeValue from the
255 * pool that is not in the pool.
257 inline void poolRemove(expr::NodeValue
* nv
);
260 * Determine if nv is currently being deleted by the NodeManager.
262 inline bool isCurrentlyDeleting(const expr::NodeValue
* nv
) const {
263 return d_nodeUnderDeletion
== nv
;
267 * Register a NodeValue as a zombie.
269 inline void markForDeletion(expr::NodeValue
* nv
) {
270 Assert(nv
->d_rc
== 0);
272 // if d_reclaiming is set, make sure we don't call
273 // reclaimZombies(), because it's already running.
274 if(Debug
.isOn("gc")) {
275 Debug("gc") << "zombifying node value " << nv
276 << " [" << nv
->d_id
<< "]: ";
277 nv
->printAst(Debug("gc"));
278 Debug("gc") << (d_inReclaimZombies
? " [CURRENTLY-RECLAIMING]" : "")
281 d_zombies
.insert(nv
); // FIXME multithreading
283 if(safeToReclaimZombies()) {
284 if(d_zombies
.size() > 5000) {
291 * Register a NodeValue as having a maxed out reference count. This NodeValue
292 * will live as long as its containing NodeManager.
294 inline void markRefCountMaxedOut(expr::NodeValue
* nv
) {
295 Assert(nv
->HasMaximizedReferenceCount());
296 if(Debug
.isOn("gc")) {
297 Debug("gc") << "marking node value " << nv
298 << " [" << nv
->d_id
<< "]: as maxed out" << std::endl
;
300 d_maxedOut
.push_back(nv
);
304 * Reclaim all zombies.
306 void reclaimZombies();
309 * It is safe to collect zombies.
311 bool safeToReclaimZombies() const;
314 * Returns a reverse topological sort of a list of NodeValues. The NodeValues
315 * must be valid and have ids. The NodeValues are not modified (including ref
318 static std::vector
<expr::NodeValue
*> TopologicalSort(
319 const std::vector
<expr::NodeValue
*>& roots
);
322 * This template gives a mechanism to stack-allocate a NodeValue
323 * with enough space for N children (where N is a compile-time
324 * constant). You use it like this:
326 * NVStorage<4> nvStorage;
327 * NodeValue& nvStack = reinterpret_cast<NodeValue&>(nvStorage);
329 * ...and then you can use nvStack as a NodeValue that you know has
330 * room for 4 children.
335 expr::NodeValue
* child
[N
];
336 };/* struct NodeManager::NVStorage<N> */
338 /* A note on isAtomic() and isAtomicFormula() (in CVC3 parlance)..
340 * It has been decided for now to hold off on implementations of
341 * these functions, as they may only be needed in CNF conversion,
342 * where it's pointless to do a lazy isAtomic determination by
343 * searching through the DAG, and storing it, since the result will
344 * only be used once. For more details see the 4/27/2010 CVC4
345 * developer's meeting notes at:
347 * http://goedel.cims.nyu.edu/wiki/Meeting_Minutes_-_April_27,_2010#isAtomic.28.29_and_isAtomicFormula.28.29
349 // bool containsDecision(TNode); // is "atomic"
350 // bool properlyContainsDecision(TNode); // all children are atomic
352 // undefined private copy constructor (disallow copy)
353 NodeManager(const NodeManager
&) CVC4_UNDEFINED
;
355 NodeManager
& operator=(const NodeManager
&) CVC4_UNDEFINED
;
360 * Create a variable with the given name and type. NOTE that no
361 * lookup is done on the name. If you mkVar("a", type) and then
362 * mkVar("a", type) again, you have two variables. The NodeManager
363 * version of this is private to avoid internal uses of mkVar() from
364 * within CVC4. Such uses should employ mkSkolem() instead.
366 Node
mkVar(const std::string
& name
, const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
367 Node
* mkVarPtr(const std::string
& name
, const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
369 /** Create a variable with the given type. */
370 Node
mkVar(const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
371 Node
* mkVarPtr(const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
375 explicit NodeManager(ExprManager
* exprManager
);
376 explicit NodeManager(ExprManager
* exprManager
, const Options
& options
);
379 /** The node manager in the current public-facing CVC4 library context */
380 static NodeManager
* currentNM() { return s_current
; }
381 /** The resource manager associated with the current node manager */
382 static ResourceManager
* currentResourceManager() { return s_current
->d_resourceManager
; }
384 /** Get this node manager's options (const version) */
385 const Options
& getOptions() const {
389 /** Get this node manager's options (non-const version) */
390 Options
& getOptions() {
394 /** Get this node manager's resource manager */
395 ResourceManager
* getResourceManager() throw() { return d_resourceManager
; }
397 /** Get this node manager's statistics registry */
398 StatisticsRegistry
* getStatisticsRegistry() const throw() {
399 return d_statisticsRegistry
;
402 /** Subscribe to NodeManager events */
403 void subscribeEvents(NodeManagerListener
* listener
) {
404 Assert(std::find(d_listeners
.begin(), d_listeners
.end(), listener
) == d_listeners
.end(), "listener already subscribed");
405 d_listeners
.push_back(listener
);
408 /** Unsubscribe from NodeManager events */
409 void unsubscribeEvents(NodeManagerListener
* listener
) {
410 std::vector
<NodeManagerListener
*>::iterator elt
= std::find(d_listeners
.begin(), d_listeners
.end(), listener
);
411 Assert(elt
!= d_listeners
.end(), "listener not subscribed");
412 d_listeners
.erase(elt
);
415 /** register datatype */
416 unsigned registerDatatype(Datatype
* dt
);
417 /** get datatype for index */
418 const Datatype
& getDatatypeForIndex( unsigned index
) const;
420 /** Get a Kind from an operator expression */
421 static inline Kind
operatorToKind(TNode n
);
423 // general expression-builders
425 /** Create a node with one child. */
426 Node
mkNode(Kind kind
, TNode child1
);
427 Node
* mkNodePtr(Kind kind
, TNode child1
);
429 /** Create a node with two children. */
430 Node
mkNode(Kind kind
, TNode child1
, TNode child2
);
431 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
);
433 /** Create a node with three children. */
434 Node
mkNode(Kind kind
, TNode child1
, TNode child2
, TNode child3
);
435 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
, TNode child3
);
437 /** Create a node with four children. */
438 Node
mkNode(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
440 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
443 /** Create a node with five children. */
444 Node
mkNode(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
445 TNode child4
, TNode child5
);
446 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
447 TNode child4
, TNode child5
);
449 /** Create a node with an arbitrary number of children. */
450 template <bool ref_count
>
451 Node
mkNode(Kind kind
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
452 template <bool ref_count
>
453 Node
* mkNodePtr(Kind kind
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
455 /** Create a node (with no children) by operator. */
456 Node
mkNode(TNode opNode
);
457 Node
* mkNodePtr(TNode opNode
);
459 /** Create a node with one child by operator. */
460 Node
mkNode(TNode opNode
, TNode child1
);
461 Node
* mkNodePtr(TNode opNode
, TNode child1
);
463 /** Create a node with two children by operator. */
464 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
);
465 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
);
467 /** Create a node with three children by operator. */
468 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
, TNode child3
);
469 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
, TNode child3
);
471 /** Create a node with four children by operator. */
472 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
474 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
477 /** Create a node with five children by operator. */
478 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
479 TNode child4
, TNode child5
);
480 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
481 TNode child4
, TNode child5
);
483 /** Create a node by applying an operator to the children. */
484 template <bool ref_count
>
485 Node
mkNode(TNode opNode
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
486 template <bool ref_count
>
487 Node
* mkNodePtr(TNode opNode
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
489 Node
mkBoundVar(const std::string
& name
, const TypeNode
& type
);
490 Node
* mkBoundVarPtr(const std::string
& name
, const TypeNode
& type
);
492 Node
mkBoundVar(const TypeNode
& type
);
493 Node
* mkBoundVarPtr(const TypeNode
& type
);
496 * Optional flags used to control behavior of NodeManager::mkSkolem().
497 * They should be composed with a bitwise OR (e.g.,
498 * "SKOLEM_NO_NOTIFY | SKOLEM_EXACT_NAME"). Of course, SKOLEM_DEFAULT
499 * cannot be composed in such a manner.
502 SKOLEM_DEFAULT
= 0, /**< default behavior */
503 SKOLEM_NO_NOTIFY
= 1, /**< do not notify subscribers */
504 SKOLEM_EXACT_NAME
= 2,/**< do not make the name unique by adding the id */
505 SKOLEM_IS_GLOBAL
= 4 /**< global vars appear in models even after a pop */
506 };/* enum SkolemFlags */
509 * Create a skolem constant with the given name, type, and comment.
511 * @param prefix the name of the new skolem variable is the prefix
512 * appended with a unique ID. This way a family of skolem variables
513 * can be made with unique identifiers, used in dump, tracing, and
514 * debugging output. Use SKOLEM_EXECT_NAME flag if you don't want
515 * a unique ID appended and use prefix as the name.
517 * @param type the type of the skolem variable to create
519 * @param comment a comment for dumping output; if declarations are
520 * being dumped, this is included in a comment before the declaration
521 * and can be quite useful for debugging
523 * @param flags an optional mask of bits from SkolemFlags to control
524 * mkSkolem() behavior
526 Node
mkSkolem(const std::string
& prefix
, const TypeNode
& type
,
527 const std::string
& comment
= "", int flags
= SKOLEM_DEFAULT
);
529 /** Create a instantiation constant with the given type. */
530 Node
mkInstConstant(const TypeNode
& type
);
532 /** Create a boolean term variable. */
533 Node
mkBooleanTermVariable();
535 /** Make a new abstract value with the given type. */
536 Node
mkAbstractValue(const TypeNode
& type
);
538 /** make unique (per Type,Kind) variable. */
539 Node
mkNullaryOperator(const TypeNode
& type
, Kind k
);
542 * Create a constant of type T. It will have the appropriate
543 * CONST_* kind defined for T.
546 Node
mkConst(const T
&);
549 TypeNode
mkTypeConst(const T
&);
551 template <class NodeClass
, class T
>
552 NodeClass
mkConstInternal(const T
&);
554 /** Create a node with children. */
555 TypeNode
mkTypeNode(Kind kind
, TypeNode child1
);
556 TypeNode
mkTypeNode(Kind kind
, TypeNode child1
, TypeNode child2
);
557 TypeNode
mkTypeNode(Kind kind
, TypeNode child1
, TypeNode child2
,
559 TypeNode
mkTypeNode(Kind kind
, const std::vector
<TypeNode
>& children
);
562 * Determine whether Nodes of a particular Kind have operators.
563 * @returns true if Nodes of Kind k have operators.
565 static inline bool hasOperator(Kind k
);
568 * Get the (singleton) operator of an OPERATOR-kinded kind. The
569 * returned node n will have kind BUILTIN, and calling
570 * n.getConst<CVC4::Kind>() will yield k.
572 inline TNode
operatorOf(Kind k
) {
573 AssertArgument( kind::metaKindOf(k
) == kind::metakind::OPERATOR
, k
,
574 "Kind is not an OPERATOR-kinded kind "
575 "in NodeManager::operatorOf()" );
576 return d_operators
[k
];
580 * Retrieve an attribute for a node.
582 * @param nv the node value
583 * @param attr an instance of the attribute kind to retrieve.
584 * @returns the attribute, if set, or a default-constructed
585 * <code>AttrKind::value_type</code> if not.
587 template <class AttrKind
>
588 inline typename
AttrKind::value_type
getAttribute(expr::NodeValue
* nv
,
589 const AttrKind
& attr
) const;
592 * Check whether an attribute is set for a node.
594 * @param nv the node value
595 * @param attr an instance of the attribute kind to check
596 * @returns <code>true</code> iff <code>attr</code> is set for
599 template <class AttrKind
>
600 inline bool hasAttribute(expr::NodeValue
* nv
,
601 const AttrKind
& attr
) const;
604 * Check whether an attribute is set for a node, and, if so,
607 * @param nv the node value
608 * @param attr an instance of the attribute kind to check
609 * @param value a reference to an object of the attribute's value type.
610 * <code>value</code> will be set to the value of the attribute, if it is
611 * set for <code>nv</code>; otherwise, it will be set to the default
612 * value of the attribute.
613 * @returns <code>true</code> iff <code>attr</code> is set for
616 template <class AttrKind
>
617 inline bool getAttribute(expr::NodeValue
* nv
,
618 const AttrKind
& attr
,
619 typename
AttrKind::value_type
& value
) const;
622 * Set an attribute for a node. If the node doesn't have the
623 * attribute, this function assigns one. If the node has one, this
626 * @param nv the node value
627 * @param attr an instance of the attribute kind to set
628 * @param value the value of <code>attr</code> for <code>nv</code>
630 template <class AttrKind
>
631 inline void setAttribute(expr::NodeValue
* nv
,
632 const AttrKind
& attr
,
633 const typename
AttrKind::value_type
& value
);
636 * Retrieve an attribute for a TNode.
639 * @param attr an instance of the attribute kind to retrieve.
640 * @returns the attribute, if set, or a default-constructed
641 * <code>AttrKind::value_type</code> if not.
643 template <class AttrKind
>
644 inline typename
AttrKind::value_type
645 getAttribute(TNode n
, const AttrKind
& attr
) const;
648 * Check whether an attribute is set for a TNode.
651 * @param attr an instance of the attribute kind to check
652 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
654 template <class AttrKind
>
655 inline bool hasAttribute(TNode n
,
656 const AttrKind
& attr
) const;
659 * Check whether an attribute is set for a TNode and, if so, retieve
663 * @param attr an instance of the attribute kind to check
664 * @param value a reference to an object of the attribute's value type.
665 * <code>value</code> will be set to the value of the attribute, if it is
666 * set for <code>nv</code>; otherwise, it will be set to the default value of
668 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
670 template <class AttrKind
>
671 inline bool getAttribute(TNode n
,
672 const AttrKind
& attr
,
673 typename
AttrKind::value_type
& value
) const;
676 * Set an attribute for a node. If the node doesn't have the
677 * attribute, this function assigns one. If the node has one, this
681 * @param attr an instance of the attribute kind to set
682 * @param value the value of <code>attr</code> for <code>n</code>
684 template <class AttrKind
>
685 inline void setAttribute(TNode n
,
686 const AttrKind
& attr
,
687 const typename
AttrKind::value_type
& value
);
690 * Retrieve an attribute for a TypeNode.
692 * @param n the type node
693 * @param attr an instance of the attribute kind to retrieve.
694 * @returns the attribute, if set, or a default-constructed
695 * <code>AttrKind::value_type</code> if not.
697 template <class AttrKind
>
698 inline typename
AttrKind::value_type
699 getAttribute(TypeNode n
, const AttrKind
& attr
) const;
702 * Check whether an attribute is set for a TypeNode.
704 * @param n the type node
705 * @param attr an instance of the attribute kind to check
706 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
708 template <class AttrKind
>
709 inline bool hasAttribute(TypeNode n
,
710 const AttrKind
& attr
) const;
713 * Check whether an attribute is set for a TypeNode and, if so, retieve
716 * @param n the type node
717 * @param attr an instance of the attribute kind to check
718 * @param value a reference to an object of the attribute's value type.
719 * <code>value</code> will be set to the value of the attribute, if it is
720 * set for <code>nv</code>; otherwise, it will be set to the default value of
722 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
724 template <class AttrKind
>
725 inline bool getAttribute(TypeNode n
,
726 const AttrKind
& attr
,
727 typename
AttrKind::value_type
& value
) const;
730 * Set an attribute for a type node. If the node doesn't have the
731 * attribute, this function assigns one. If the type node has one,
732 * this overwrites it.
734 * @param n the type node
735 * @param attr an instance of the attribute kind to set
736 * @param value the value of <code>attr</code> for <code>n</code>
738 template <class AttrKind
>
739 inline void setAttribute(TypeNode n
,
740 const AttrKind
& attr
,
741 const typename
AttrKind::value_type
& value
);
743 /** Get the (singleton) type for Booleans. */
744 inline TypeNode
booleanType();
746 /** Get the (singleton) type for integers. */
747 inline TypeNode
integerType();
749 /** Get the (singleton) type for reals. */
750 inline TypeNode
realType();
752 /** Get the (singleton) type for strings. */
753 inline TypeNode
stringType();
755 /** Get the (singleton) type for RegExp. */
756 inline TypeNode
regExpType();
758 /** Get the (singleton) type for rounding modes. */
759 inline TypeNode
roundingModeType();
761 /** Get the bound var list type. */
762 inline TypeNode
boundVarListType();
764 /** Get the instantiation pattern type. */
765 inline TypeNode
instPatternType();
767 /** Get the instantiation pattern type. */
768 inline TypeNode
instPatternListType();
771 * Get the (singleton) type for builtin operators (that is, the type
772 * of the Node returned from Node::getOperator() when the operator
773 * is built-in, like EQUAL). */
774 inline TypeNode
builtinOperatorType();
777 * Make a function type from domain to range.
779 * @param domain the domain type
780 * @param range the range type
781 * @returns the functional type domain -> range
783 inline TypeNode
mkFunctionType(const TypeNode
& domain
, const TypeNode
& range
);
786 * Make a function type with input types from
787 * argTypes. <code>argTypes</code> must have at least one element.
789 * @param argTypes the domain is a tuple (argTypes[0], ..., argTypes[n])
790 * @param range the range type
791 * @returns the functional type (argTypes[0], ..., argTypes[n]) -> range
793 inline TypeNode
mkFunctionType(const std::vector
<TypeNode
>& argTypes
,
794 const TypeNode
& range
);
797 * Make a function type with input types from
798 * <code>sorts[0..sorts.size()-2]</code> and result type
799 * <code>sorts[sorts.size()-1]</code>. <code>sorts</code> must have
800 * at least 2 elements.
802 inline TypeNode
mkFunctionType(const std::vector
<TypeNode
>& sorts
);
805 * Make a predicate type with input types from
806 * <code>sorts</code>. The result with be a function type with range
807 * <code>BOOLEAN</code>. <code>sorts</code> must have at least one
810 inline TypeNode
mkPredicateType(const std::vector
<TypeNode
>& sorts
);
813 * Make a tuple type with types from
814 * <code>types</code>. <code>types</code> must have at least one
817 * @param types a vector of types
818 * @returns the tuple type (types[0], ..., types[n])
820 TypeNode
mkTupleType(const std::vector
<TypeNode
>& types
);
823 * Make a record type with the description from rec.
825 * @param rec a description of the record
826 * @returns the record type
828 TypeNode
mkRecordType(const Record
& rec
);
831 * Make a symbolic expression type with types from
832 * <code>types</code>. <code>types</code> may have any number of
835 * @param types a vector of types
836 * @returns the symbolic expression type (types[0], ..., types[n])
838 inline TypeNode
mkSExprType(const std::vector
<TypeNode
>& types
);
840 /** Make the type of floating-point with <code>exp</code> bit exponent and
841 <code>sig</code> bit significand */
842 inline TypeNode
mkFloatingPointType(unsigned exp
, unsigned sig
);
843 inline TypeNode
mkFloatingPointType(FloatingPointSize fs
);
845 /** Make the type of bitvectors of size <code>size</code> */
846 inline TypeNode
mkBitVectorType(unsigned size
);
848 /** Make the type of arrays with the given parameterization */
849 inline TypeNode
mkArrayType(TypeNode indexType
, TypeNode constituentType
);
851 /** Make the type of arrays with the given parameterization */
852 inline TypeNode
mkSetType(TypeNode elementType
);
854 /** Make a type representing a constructor with the given parameterization */
855 TypeNode
mkConstructorType(const DatatypeConstructor
& constructor
, TypeNode range
);
857 /** Make a type representing a selector with the given parameterization */
858 inline TypeNode
mkSelectorType(TypeNode domain
, TypeNode range
);
860 /** Make a type representing a tester with given parameterization */
861 inline TypeNode
mkTesterType(TypeNode domain
);
863 /** Make a new (anonymous) sort of arity 0. */
864 TypeNode
mkSort(uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
866 /** Make a new sort with the given name of arity 0. */
867 TypeNode
mkSort(const std::string
& name
, uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
869 /** Make a new sort by parameterizing the given sort constructor. */
870 TypeNode
mkSort(TypeNode constructor
,
871 const std::vector
<TypeNode
>& children
,
872 uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
874 /** Make a new sort with the given name and arity. */
875 TypeNode
mkSortConstructor(const std::string
& name
, size_t arity
);
878 * Get the type for the given node and optionally do type checking.
880 * Initial type computation will be near-constant time if
881 * type checking is not requested. Results are memoized, so that
882 * subsequent calls to getType() without type checking will be
885 * Initial type checking is linear in the size of the expression.
886 * Again, the results are memoized, so that subsequent calls to
887 * getType(), with or without type checking, will be constant
890 * NOTE: A TypeCheckingException can be thrown even when type
891 * checking is not requested. getType() will always return a
892 * valid and correct type and, thus, an exception will be thrown
893 * when no valid or correct type can be computed (e.g., if the
894 * arguments to a bit-vector operation aren't bit-vectors). When
895 * type checking is not requested, getType() will do the minimum
896 * amount of checking required to return a valid result.
898 * @param n the Node for which we want a type
899 * @param check whether we should check the type as we compute it
902 TypeNode
getType(TNode n
, bool check
= false)
903 throw(TypeCheckingExceptionPrivate
, AssertionException
);
906 * Convert a node to an expression. Uses the ExprManager
907 * associated to this NodeManager.
909 inline Expr
toExpr(TNode n
);
912 * Convert an expression to a node.
914 static inline Node
fromExpr(const Expr
& e
);
917 * Convert a node manager to an expression manager.
919 inline ExprManager
* toExprManager();
922 * Convert an expression manager to a node manager.
924 static inline NodeManager
* fromExprManager(ExprManager
* exprManager
);
927 * Convert a type node to a type.
929 inline Type
toType(TypeNode tn
);
932 * Convert a type to a type node.
934 static inline TypeNode
fromType(Type t
);
936 /** Reclaim zombies while there are more than k nodes in the pool (if possible).*/
937 void reclaimZombiesUntil(uint32_t k
);
939 /** Reclaims all zombies (if possible).*/
940 void reclaimAllZombies();
942 /** Size of the node pool. */
943 size_t poolSize() const;
945 /** Deletes a list of attributes from the NM's AttributeManager.*/
946 void deleteAttributes(const std::vector
< const expr::attr::AttributeUniqueId
* >& ids
);
949 * This function gives developers a hook into the NodeManager.
950 * This can be changed in node_manager.cpp without recompiling most of cvc4.
952 * debugHook is a debugging only function, and should not be present in
953 * any published code!
955 void debugHook(int debugFlag
);
956 };/* class NodeManager */
959 * This class changes the "current" thread-global
960 * <code>NodeManager</code> when it is created and reinstates the
961 * previous thread-global <code>NodeManager</code> when it is
962 * destroyed, effectively maintaining a set of nested
963 * <code>NodeManager</code> scopes. This is especially useful on
964 * public-interface calls into the CVC4 library, where CVC4's notion
965 * of the "current" <code>NodeManager</code> should be set to match
966 * the calling context. See, for example, the implementations of
967 * public calls in the <code>ExprManager</code> and
968 * <code>SmtEngine</code> classes.
970 * The client must be careful to create and destroy
971 * <code>NodeManagerScope</code> objects in a well-nested manner (such
972 * as on the stack). You may create a <code>NodeManagerScope</code>
973 * with <code>new</code> and destroy it with <code>delete</code>, or
974 * place it as a data member of an object that is, but if the scope of
975 * these <code>new</code>/<code>delete</code> pairs isn't properly
976 * maintained, the incorrect "current" <code>NodeManager</code>
977 * pointer may be restored after a delete.
979 class NodeManagerScope
{
980 /** The old NodeManager, to be restored on destruction. */
981 NodeManager
* d_oldNodeManager
;
982 Options::OptionsScope d_optionsScope
;
985 NodeManagerScope(NodeManager
* nm
)
986 : d_oldNodeManager(NodeManager::s_current
)
987 , d_optionsScope(nm
? nm
->d_options
: NULL
) {
988 // There are corner cases where nm can be NULL and it's ok.
989 // For example, if you write { Expr e; }, then when the null
990 // Expr is destructed, there's no active node manager.
991 //Assert(nm != NULL);
992 NodeManager::s_current
= nm
;
993 //Options::s_current = nm ? nm->d_options : NULL;
994 Debug("current") << "node manager scope: "
995 << NodeManager::s_current
<< "\n";
998 ~NodeManagerScope() {
999 NodeManager::s_current
= d_oldNodeManager
;
1000 //Options::s_current = d_oldNodeManager ? d_oldNodeManager->d_options : NULL;
1001 Debug("current") << "node manager scope: "
1002 << "returning to " << NodeManager::s_current
<< "\n";
1004 };/* class NodeManagerScope */
1006 /** Get the (singleton) type for booleans. */
1007 inline TypeNode
NodeManager::booleanType() {
1008 return TypeNode(mkTypeConst
<TypeConstant
>(BOOLEAN_TYPE
));
1011 /** Get the (singleton) type for integers. */
1012 inline TypeNode
NodeManager::integerType() {
1013 return TypeNode(mkTypeConst
<TypeConstant
>(INTEGER_TYPE
));
1016 /** Get the (singleton) type for reals. */
1017 inline TypeNode
NodeManager::realType() {
1018 return TypeNode(mkTypeConst
<TypeConstant
>(REAL_TYPE
));
1021 /** Get the (singleton) type for strings. */
1022 inline TypeNode
NodeManager::stringType() {
1023 return TypeNode(mkTypeConst
<TypeConstant
>(STRING_TYPE
));
1026 /** Get the (singleton) type for regexps. */
1027 inline TypeNode
NodeManager::regExpType() {
1028 return TypeNode(mkTypeConst
<TypeConstant
>(REGEXP_TYPE
));
1031 /** Get the (singleton) type for rounding modes. */
1032 inline TypeNode
NodeManager::roundingModeType() {
1033 return TypeNode(mkTypeConst
<TypeConstant
>(ROUNDINGMODE_TYPE
));
1036 /** Get the bound var list type. */
1037 inline TypeNode
NodeManager::boundVarListType() {
1038 return TypeNode(mkTypeConst
<TypeConstant
>(BOUND_VAR_LIST_TYPE
));
1041 /** Get the instantiation pattern type. */
1042 inline TypeNode
NodeManager::instPatternType() {
1043 return TypeNode(mkTypeConst
<TypeConstant
>(INST_PATTERN_TYPE
));
1046 /** Get the instantiation pattern type. */
1047 inline TypeNode
NodeManager::instPatternListType() {
1048 return TypeNode(mkTypeConst
<TypeConstant
>(INST_PATTERN_LIST_TYPE
));
1051 /** Get the (singleton) type for builtin operators. */
1052 inline TypeNode
NodeManager::builtinOperatorType() {
1053 return TypeNode(mkTypeConst
<TypeConstant
>(BUILTIN_OPERATOR_TYPE
));
1056 /** Make a function type from domain to range. */
1057 inline TypeNode
NodeManager::mkFunctionType(const TypeNode
& domain
, const TypeNode
& range
) {
1058 std::vector
<TypeNode
> sorts
;
1059 sorts
.push_back(domain
);
1060 sorts
.push_back(range
);
1061 return mkFunctionType(sorts
);
1064 inline TypeNode
NodeManager::mkFunctionType(const std::vector
<TypeNode
>& argTypes
, const TypeNode
& range
) {
1065 Assert(argTypes
.size() >= 1);
1066 std::vector
<TypeNode
> sorts(argTypes
);
1067 sorts
.push_back(range
);
1068 return mkFunctionType(sorts
);
1072 NodeManager::mkFunctionType(const std::vector
<TypeNode
>& sorts
) {
1073 Assert(sorts
.size() >= 2);
1074 std::vector
<TypeNode
> sortNodes
;
1075 for (unsigned i
= 0; i
< sorts
.size(); ++ i
) {
1076 CheckArgument(!sorts
[i
].isFunctionLike(), sorts
,
1077 "cannot create higher-order function types");
1078 sortNodes
.push_back(sorts
[i
]);
1080 return mkTypeNode(kind::FUNCTION_TYPE
, sortNodes
);
1084 NodeManager::mkPredicateType(const std::vector
<TypeNode
>& sorts
) {
1085 Assert(sorts
.size() >= 1);
1086 std::vector
<TypeNode
> sortNodes
;
1087 for (unsigned i
= 0; i
< sorts
.size(); ++ i
) {
1088 CheckArgument(!sorts
[i
].isFunctionLike(), sorts
,
1089 "cannot create higher-order function types");
1090 sortNodes
.push_back(sorts
[i
]);
1092 sortNodes
.push_back(booleanType());
1093 return mkTypeNode(kind::FUNCTION_TYPE
, sortNodes
);
1096 inline TypeNode
NodeManager::mkSExprType(const std::vector
<TypeNode
>& types
) {
1097 std::vector
<TypeNode
> typeNodes
;
1098 for (unsigned i
= 0; i
< types
.size(); ++ i
) {
1099 typeNodes
.push_back(types
[i
]);
1101 return mkTypeNode(kind::SEXPR_TYPE
, typeNodes
);
1104 inline TypeNode
NodeManager::mkBitVectorType(unsigned size
) {
1105 return TypeNode(mkTypeConst
<BitVectorSize
>(BitVectorSize(size
)));
1108 inline TypeNode
NodeManager::mkFloatingPointType(unsigned exp
, unsigned sig
) {
1109 return TypeNode(mkTypeConst
<FloatingPointSize
>(FloatingPointSize(exp
,sig
)));
1112 inline TypeNode
NodeManager::mkFloatingPointType(FloatingPointSize fs
) {
1113 return TypeNode(mkTypeConst
<FloatingPointSize
>(fs
));
1116 inline TypeNode
NodeManager::mkArrayType(TypeNode indexType
,
1117 TypeNode constituentType
) {
1118 CheckArgument(!indexType
.isNull(), indexType
,
1119 "unexpected NULL index type");
1120 CheckArgument(!constituentType
.isNull(), constituentType
,
1121 "unexpected NULL constituent type");
1122 CheckArgument(!indexType
.isFunctionLike(), indexType
,
1123 "cannot index arrays by a function-like type");
1124 CheckArgument(!constituentType
.isFunctionLike(), constituentType
,
1125 "cannot store function-like types in arrays");
1126 Debug("arrays") << "making array type " << indexType
<< " "
1127 << constituentType
<< std::endl
;
1128 return mkTypeNode(kind::ARRAY_TYPE
, indexType
, constituentType
);
1131 inline TypeNode
NodeManager::mkSetType(TypeNode elementType
) {
1132 CheckArgument(!elementType
.isNull(), elementType
,
1133 "unexpected NULL element type");
1134 // TODO: Confirm meaning of isFunctionLike(). --K
1135 CheckArgument(!elementType
.isFunctionLike(), elementType
,
1136 "cannot store function-like types in sets");
1137 Debug("sets") << "making sets type " << elementType
<< std::endl
;
1138 return mkTypeNode(kind::SET_TYPE
, elementType
);
1141 inline TypeNode
NodeManager::mkSelectorType(TypeNode domain
, TypeNode range
) {
1142 CheckArgument(!domain
.isFunctionLike(), domain
,
1143 "cannot create higher-order function types");
1144 CheckArgument(!range
.isFunctionLike(), range
,
1145 "cannot create higher-order function types");
1146 return mkTypeNode(kind::SELECTOR_TYPE
, domain
, range
);
1149 inline TypeNode
NodeManager::mkTesterType(TypeNode domain
) {
1150 CheckArgument(!domain
.isFunctionLike(), domain
,
1151 "cannot create higher-order function types");
1152 return mkTypeNode(kind::TESTER_TYPE
, domain
);
1155 inline expr::NodeValue
* NodeManager::poolLookup(expr::NodeValue
* nv
) const {
1156 NodeValuePool::const_iterator find
= d_nodeValuePool
.find(nv
);
1157 if(find
== d_nodeValuePool
.end()) {
1164 inline void NodeManager::poolInsert(expr::NodeValue
* nv
) {
1165 Assert(d_nodeValuePool
.find(nv
) == d_nodeValuePool
.end(),
1166 "NodeValue already in the pool!");
1167 d_nodeValuePool
.insert(nv
);// FIXME multithreading
1170 inline void NodeManager::poolRemove(expr::NodeValue
* nv
) {
1171 Assert(d_nodeValuePool
.find(nv
) != d_nodeValuePool
.end(),
1172 "NodeValue is not in the pool!");
1174 d_nodeValuePool
.erase(nv
);// FIXME multithreading
1177 inline Expr
NodeManager::toExpr(TNode n
) {
1178 return Expr(d_exprManager
, new Node(n
));
1181 inline Node
NodeManager::fromExpr(const Expr
& e
) {
1185 inline ExprManager
* NodeManager::toExprManager() {
1186 return d_exprManager
;
1189 inline NodeManager
* NodeManager::fromExprManager(ExprManager
* exprManager
) {
1190 return exprManager
->getNodeManager();
1193 inline Type
NodeManager::toType(TypeNode tn
) {
1194 return Type(this, new TypeNode(tn
));
1197 inline TypeNode
NodeManager::fromType(Type t
) {
1198 return *Type::getTypeNode(t
);
1201 }/* CVC4 namespace */
1203 #define __CVC4__NODE_MANAGER_NEEDS_CONSTANT_MAP
1204 #include "expr/metakind.h"
1205 #undef __CVC4__NODE_MANAGER_NEEDS_CONSTANT_MAP
1207 #include "expr/node_builder.h"
1211 // general expression-builders
1213 inline bool NodeManager::hasOperator(Kind k
) {
1214 switch(kind::MetaKind mk
= kind::metaKindOf(k
)) {
1216 case kind::metakind::INVALID
:
1217 case kind::metakind::VARIABLE
:
1218 case kind::metakind::NULLARY_OPERATOR
:
1221 case kind::metakind::OPERATOR
:
1222 case kind::metakind::PARAMETERIZED
:
1225 case kind::metakind::CONSTANT
:
1233 inline Kind
NodeManager::operatorToKind(TNode n
) {
1234 return kind::operatorToKind(n
.d_nv
);
1237 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
) {
1238 NodeBuilder
<1> nb(this, kind
);
1240 return nb
.constructNode();
1243 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
) {
1244 NodeBuilder
<1> nb(this, kind
);
1246 return nb
.constructNodePtr();
1249 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
) {
1250 NodeBuilder
<2> nb(this, kind
);
1251 nb
<< child1
<< child2
;
1252 return nb
.constructNode();
1255 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
) {
1256 NodeBuilder
<2> nb(this, kind
);
1257 nb
<< child1
<< child2
;
1258 return nb
.constructNodePtr();
1261 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
,
1263 NodeBuilder
<3> nb(this, kind
);
1264 nb
<< child1
<< child2
<< child3
;
1265 return nb
.constructNode();
1268 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
,
1270 NodeBuilder
<3> nb(this, kind
);
1271 nb
<< child1
<< child2
<< child3
;
1272 return nb
.constructNodePtr();
1275 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
,
1276 TNode child3
, TNode child4
) {
1277 NodeBuilder
<4> nb(this, kind
);
1278 nb
<< child1
<< child2
<< child3
<< child4
;
1279 return nb
.constructNode();
1282 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
,
1283 TNode child3
, TNode child4
) {
1284 NodeBuilder
<4> nb(this, kind
);
1285 nb
<< child1
<< child2
<< child3
<< child4
;
1286 return nb
.constructNodePtr();
1289 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
,
1290 TNode child3
, TNode child4
, TNode child5
) {
1291 NodeBuilder
<5> nb(this, kind
);
1292 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1293 return nb
.constructNode();
1296 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
,
1297 TNode child3
, TNode child4
, TNode child5
) {
1298 NodeBuilder
<5> nb(this, kind
);
1299 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1300 return nb
.constructNodePtr();
1304 template <bool ref_count
>
1305 inline Node
NodeManager::mkNode(Kind kind
,
1306 const std::vector
<NodeTemplate
<ref_count
> >&
1308 NodeBuilder
<> nb(this, kind
);
1309 nb
.append(children
);
1310 return nb
.constructNode();
1313 template <bool ref_count
>
1314 inline Node
* NodeManager::mkNodePtr(Kind kind
,
1315 const std::vector
<NodeTemplate
<ref_count
> >&
1317 NodeBuilder
<> nb(this, kind
);
1318 nb
.append(children
);
1319 return nb
.constructNodePtr();
1323 inline Node
NodeManager::mkNode(TNode opNode
) {
1324 NodeBuilder
<1> nb(this, operatorToKind(opNode
));
1325 if(opNode
.getKind() != kind::BUILTIN
) {
1328 return nb
.constructNode();
1331 inline Node
* NodeManager::mkNodePtr(TNode opNode
) {
1332 NodeBuilder
<1> nb(this, operatorToKind(opNode
));
1333 if(opNode
.getKind() != kind::BUILTIN
) {
1336 return nb
.constructNodePtr();
1339 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
) {
1340 NodeBuilder
<2> nb(this, operatorToKind(opNode
));
1341 if(opNode
.getKind() != kind::BUILTIN
) {
1345 return nb
.constructNode();
1348 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
) {
1349 NodeBuilder
<2> nb(this, operatorToKind(opNode
));
1350 if(opNode
.getKind() != kind::BUILTIN
) {
1354 return nb
.constructNodePtr();
1357 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
) {
1358 NodeBuilder
<3> nb(this, operatorToKind(opNode
));
1359 if(opNode
.getKind() != kind::BUILTIN
) {
1362 nb
<< child1
<< child2
;
1363 return nb
.constructNode();
1366 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
) {
1367 NodeBuilder
<3> nb(this, operatorToKind(opNode
));
1368 if(opNode
.getKind() != kind::BUILTIN
) {
1371 nb
<< child1
<< child2
;
1372 return nb
.constructNodePtr();
1375 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
,
1377 NodeBuilder
<4> nb(this, operatorToKind(opNode
));
1378 if(opNode
.getKind() != kind::BUILTIN
) {
1381 nb
<< child1
<< child2
<< child3
;
1382 return nb
.constructNode();
1385 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
,
1387 NodeBuilder
<4> nb(this, operatorToKind(opNode
));
1388 if(opNode
.getKind() != kind::BUILTIN
) {
1391 nb
<< child1
<< child2
<< child3
;
1392 return nb
.constructNodePtr();
1395 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
,
1396 TNode child3
, TNode child4
) {
1397 NodeBuilder
<5> nb(this, operatorToKind(opNode
));
1398 if(opNode
.getKind() != kind::BUILTIN
) {
1401 nb
<< child1
<< child2
<< child3
<< child4
;
1402 return nb
.constructNode();
1405 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
,
1406 TNode child3
, TNode child4
) {
1407 NodeBuilder
<5> nb(this, operatorToKind(opNode
));
1408 if(opNode
.getKind() != kind::BUILTIN
) {
1411 nb
<< child1
<< child2
<< child3
<< child4
;
1412 return nb
.constructNodePtr();
1415 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
,
1416 TNode child3
, TNode child4
, TNode child5
) {
1417 NodeBuilder
<6> nb(this, operatorToKind(opNode
));
1418 if(opNode
.getKind() != kind::BUILTIN
) {
1421 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1422 return nb
.constructNode();
1425 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
,
1426 TNode child3
, TNode child4
, TNode child5
) {
1427 NodeBuilder
<6> nb(this, operatorToKind(opNode
));
1428 if(opNode
.getKind() != kind::BUILTIN
) {
1431 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1432 return nb
.constructNodePtr();
1435 // N-ary version for operators
1436 template <bool ref_count
>
1437 inline Node
NodeManager::mkNode(TNode opNode
,
1438 const std::vector
<NodeTemplate
<ref_count
> >&
1440 NodeBuilder
<> nb(this, operatorToKind(opNode
));
1441 if(opNode
.getKind() != kind::BUILTIN
) {
1444 nb
.append(children
);
1445 return nb
.constructNode();
1448 template <bool ref_count
>
1449 inline Node
* NodeManager::mkNodePtr(TNode opNode
,
1450 const std::vector
<NodeTemplate
<ref_count
> >&
1452 NodeBuilder
<> nb(this, operatorToKind(opNode
));
1453 if(opNode
.getKind() != kind::BUILTIN
) {
1456 nb
.append(children
);
1457 return nb
.constructNodePtr();
1461 inline TypeNode
NodeManager::mkTypeNode(Kind kind
, TypeNode child1
) {
1462 return (NodeBuilder
<1>(this, kind
) << child1
).constructTypeNode();
1465 inline TypeNode
NodeManager::mkTypeNode(Kind kind
, TypeNode child1
,
1467 return (NodeBuilder
<2>(this, kind
) << child1
<< child2
).constructTypeNode();
1470 inline TypeNode
NodeManager::mkTypeNode(Kind kind
, TypeNode child1
,
1471 TypeNode child2
, TypeNode child3
) {
1472 return (NodeBuilder
<3>(this, kind
) << child1
<< child2
<< child3
).constructTypeNode();
1475 // N-ary version for types
1476 inline TypeNode
NodeManager::mkTypeNode(Kind kind
,
1477 const std::vector
<TypeNode
>& children
) {
1478 return NodeBuilder
<>(this, kind
).append(children
).constructTypeNode();
1482 Node
NodeManager::mkConst(const T
& val
) {
1483 return mkConstInternal
<Node
, T
>(val
);
1487 TypeNode
NodeManager::mkTypeConst(const T
& val
) {
1488 return mkConstInternal
<TypeNode
, T
>(val
);
1491 template <class NodeClass
, class T
>
1492 NodeClass
NodeManager::mkConstInternal(const T
& val
) {
1494 // typedef typename kind::metakind::constantMap<T>::OwningTheory theory_t;
1495 NVStorage
<1> nvStorage
;
1496 expr::NodeValue
& nvStack
= reinterpret_cast<expr::NodeValue
&>(nvStorage
);
1499 nvStack
.d_kind
= kind::metakind::ConstantMap
<T
>::kind
;
1501 nvStack
.d_nchildren
= 1;
1503 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1504 #pragma GCC diagnostic push
1505 #pragma GCC diagnostic ignored "-Warray-bounds"
1508 nvStack
.d_children
[0] =
1509 const_cast<expr::NodeValue
*>(reinterpret_cast<const expr::NodeValue
*>(&val
));
1510 expr::NodeValue
* nv
= poolLookup(&nvStack
);
1512 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1513 #pragma GCC diagnostic pop
1517 return NodeClass(nv
);
1520 nv
= (expr::NodeValue
*)
1521 std::malloc(sizeof(expr::NodeValue
) + sizeof(T
));
1523 throw std::bad_alloc();
1526 nv
->d_nchildren
= 0;
1527 nv
->d_kind
= kind::metakind::ConstantMap
<T
>::kind
;
1528 nv
->d_id
= next_id
++;// FIXME multithreading
1531 //OwningTheory::mkConst(val);
1532 new (&nv
->d_children
) T(val
);
1535 if(Debug
.isOn("gc")) {
1536 Debug("gc") << "creating node value " << nv
1537 << " [" << nv
->d_id
<< "]: ";
1538 nv
->printAst(Debug("gc"));
1539 Debug("gc") << std::endl
;
1542 return NodeClass(nv
);
1545 }/* CVC4 namespace */
1547 #endif /* __CVC4__NODE_MANAGER_H */