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-2018 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 <unordered_set>
35 #include "expr/kind.h"
36 #include "expr/metakind.h"
37 #include "expr/node_value.h"
38 #include "options/options.h"
42 class StatisticsRegistry
;
43 class ResourceManager
;
47 class AttributeUniqueId
;
48 class AttributeManager
;
49 }/* CVC4::expr::attr namespace */
52 }/* CVC4::expr namespace */
55 * An interface that an interested party can implement and then subscribe
56 * to NodeManager events via NodeManager::subscribeEvents(this).
58 class NodeManagerListener
{
60 virtual ~NodeManagerListener() {}
61 virtual void nmNotifyNewSort(TypeNode tn
, uint32_t flags
) {}
62 virtual void nmNotifyNewSortConstructor(TypeNode tn
, uint32_t flags
) {}
63 virtual void nmNotifyInstantiateSortConstructor(TypeNode ctor
, TypeNode sort
,
65 virtual void nmNotifyNewDatatypes(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(
92 std::vector
<Datatype
>&, std::set
<Type
>&, uint32_t);
94 /** Predicate for use with STL algorithms */
95 struct NodeValueReferenceCountNonZero
{
96 bool operator()(expr::NodeValue
* nv
) { return nv
->d_rc
> 0; }
99 typedef std::unordered_set
<expr::NodeValue
*,
100 expr::NodeValuePoolHashFunction
,
101 expr::NodeValuePoolEq
> NodeValuePool
;
102 typedef std::unordered_set
<expr::NodeValue
*,
103 expr::NodeValueIDHashFunction
,
104 expr::NodeValueIDEquality
> NodeValueIDSet
;
106 static thread_local NodeManager
* s_current
;
109 StatisticsRegistry
* d_statisticsRegistry
;
111 ResourceManager
* d_resourceManager
;
114 * A list of registrations on d_options to that call into d_resourceManager.
115 * These must be garbage collected before d_options and d_resourceManager.
117 ListenerRegistrationList
* d_registrations
;
119 NodeValuePool d_nodeValuePool
;
123 expr::attr::AttributeManager
* d_attrManager
;
125 /** The associated ExprManager */
126 ExprManager
* d_exprManager
;
129 * The node value we're currently freeing. This unique node value
130 * is permitted to have outstanding TNodes to it (in "soft"
131 * contexts, like as a key in attribute tables), even though
132 * normally it's an error to have a TNode to a node value with a
133 * reference count of 0. Being "under deletion" also enables
134 * assertions that inc() is not called on it.
136 expr::NodeValue
* d_nodeUnderDeletion
;
139 * True iff we are in reclaimZombies(). This avoids unnecessary
140 * recursion; a NodeValue being deleted might zombify other
141 * NodeValues, but these shouldn't trigger a (recursive) call to
144 bool d_inReclaimZombies
;
147 * The set of zombie nodes. We may want to revisit this design, as
148 * we might like to delete nodes in least-recently-used order. But
149 * we also need to avoid processing a zombie twice.
151 NodeValueIDSet d_zombies
;
154 * NodeValues with maxed out reference counts. These live as long as the
155 * NodeManager. They have a custom deallocation procedure at the very end.
157 std::vector
<expr::NodeValue
*> d_maxedOut
;
160 * A set of operator singletons (w.r.t. to this NodeManager
161 * instance) for operators. Conceptually, Nodes with kind, say,
162 * PLUS, are APPLYs of a PLUS operator to arguments. This array
163 * holds the set of operators for these things. A PLUS operator is
164 * a Node with kind "BUILTIN", and if you call
165 * plusOperator->getConst<CVC4::Kind>(), you get kind::PLUS back.
167 Node d_operators
[kind::LAST_KIND
];
169 /** unique vars per (Kind,Type) */
170 std::map
< Kind
, std::map
< TypeNode
, Node
> > d_unique_vars
;
173 * A list of subscribers for NodeManager events.
175 std::vector
<NodeManagerListener
*> d_listeners
;
177 /** A list of datatypes owned by this node manager. */
178 std::vector
<Datatype
*> d_ownedDatatypes
;
181 * A map of tuple and record types to their corresponding datatype.
183 class TupleTypeCache
{
185 std::map
< TypeNode
, TupleTypeCache
> d_children
;
187 TypeNode
getTupleType( NodeManager
* nm
, std::vector
< TypeNode
>& types
, unsigned index
= 0 );
191 std::map
< TypeNode
, std::map
< std::string
, RecTypeCache
> > d_children
;
193 TypeNode
getRecordType( NodeManager
* nm
, const Record
& rec
, unsigned index
= 0 );
195 TupleTypeCache d_tt_cache
;
196 RecTypeCache d_rt_cache
;
199 * Keep a count of all abstract values produced by this NodeManager.
200 * Abstract values have a type attribute, so if multiple SmtEngines
201 * are attached to this NodeManager, we don't want their abstract
204 unsigned d_abstractValueCount
;
207 * A counter used to produce unique skolem names.
209 * Note that it is NOT incremented when skolems are created using
210 * SKOLEM_EXACT_NAME, so it is NOT a count of the skolems produced
211 * by this node manager.
213 unsigned d_skolemCounter
;
216 * Look up a NodeValue in the pool associated to this NodeManager.
217 * The NodeValue argument need not be a "completely-constructed"
218 * NodeValue. In particular, "non-inlined" constants are permitted
221 * For non-CONSTANT metakinds, nv's d_kind and d_nchildren should be
222 * correctly set, and d_children[0..n-1] should be valid (extant)
223 * NodeValues for lookup.
225 * For CONSTANT metakinds, nv's d_kind should be set correctly.
226 * Normally a CONSTANT would have d_nchildren == 0 and the constant
227 * value inlined in the d_children space. However, here we permit
228 * "non-inlined" NodeValues to avoid unnecessary copying. For
229 * these, d_nchildren == 1, and d_nchildren is a pointer to the
232 * The point of this complex design is to permit efficient lookups
233 * (without fully constructing a NodeValue). In the case that the
234 * argument is not fully constructed, and this function returns
235 * NULL, the caller should fully construct an equivalent one before
236 * calling poolInsert(). NON-FULLY-CONSTRUCTED NODEVALUES are not
237 * permitted in the pool!
239 inline expr::NodeValue
* poolLookup(expr::NodeValue
* nv
) const;
242 * Insert a NodeValue into the NodeManager's pool.
244 * It is an error to insert a NodeValue already in the pool.
245 * Enquire first with poolLookup().
247 inline void poolInsert(expr::NodeValue
* nv
);
250 * Remove a NodeValue from the NodeManager's pool.
252 * It is an error to request the removal of a NodeValue from the
253 * pool that is not in the pool.
255 inline void poolRemove(expr::NodeValue
* nv
);
258 * Determine if nv is currently being deleted by the NodeManager.
260 inline bool isCurrentlyDeleting(const expr::NodeValue
* nv
) const {
261 return d_nodeUnderDeletion
== nv
;
265 * Register a NodeValue as a zombie.
267 inline void markForDeletion(expr::NodeValue
* nv
) {
268 Assert(nv
->d_rc
== 0);
270 // if d_reclaiming is set, make sure we don't call
271 // reclaimZombies(), because it's already running.
272 if(Debug
.isOn("gc")) {
273 Debug("gc") << "zombifying node value " << nv
274 << " [" << nv
->d_id
<< "]: ";
275 nv
->printAst(Debug("gc"));
276 Debug("gc") << (d_inReclaimZombies
? " [CURRENTLY-RECLAIMING]" : "")
279 d_zombies
.insert(nv
); // FIXME multithreading
281 if(safeToReclaimZombies()) {
282 if(d_zombies
.size() > 5000) {
289 * Register a NodeValue as having a maxed out reference count. This NodeValue
290 * will live as long as its containing NodeManager.
292 inline void markRefCountMaxedOut(expr::NodeValue
* nv
) {
293 Assert(nv
->HasMaximizedReferenceCount());
294 if(Debug
.isOn("gc")) {
295 Debug("gc") << "marking node value " << nv
296 << " [" << nv
->d_id
<< "]: as maxed out" << std::endl
;
298 d_maxedOut
.push_back(nv
);
302 * Reclaim all zombies.
304 void reclaimZombies();
307 * It is safe to collect zombies.
309 bool safeToReclaimZombies() const;
312 * Returns a reverse topological sort of a list of NodeValues. The NodeValues
313 * must be valid and have ids. The NodeValues are not modified (including ref
316 static std::vector
<expr::NodeValue
*> TopologicalSort(
317 const std::vector
<expr::NodeValue
*>& roots
);
320 * This template gives a mechanism to stack-allocate a NodeValue
321 * with enough space for N children (where N is a compile-time
322 * constant). You use it like this:
324 * NVStorage<4> nvStorage;
325 * NodeValue& nvStack = reinterpret_cast<NodeValue&>(nvStorage);
327 * ...and then you can use nvStack as a NodeValue that you know has
328 * room for 4 children.
333 expr::NodeValue
* child
[N
];
334 };/* struct NodeManager::NVStorage<N> */
336 /* A note on isAtomic() and isAtomicFormula() (in CVC3 parlance)..
338 * It has been decided for now to hold off on implementations of
339 * these functions, as they may only be needed in CNF conversion,
340 * where it's pointless to do a lazy isAtomic determination by
341 * searching through the DAG, and storing it, since the result will
342 * only be used once. For more details see the 4/27/2010 CVC4
343 * developer's meeting notes at:
345 * http://cvc4.cs.stanford.edu/wiki/Meeting_Minutes_-_April_27,_2010#isAtomic.28.29_and_isAtomicFormula.28.29
347 // bool containsDecision(TNode); // is "atomic"
348 // bool properlyContainsDecision(TNode); // all children are atomic
350 // undefined private copy constructor (disallow copy)
351 NodeManager(const NodeManager
&) = delete;
353 NodeManager
& operator=(const NodeManager
&) = delete;
358 * Create a variable with the given name and type. NOTE that no
359 * lookup is done on the name. If you mkVar("a", type) and then
360 * mkVar("a", type) again, you have two variables. The NodeManager
361 * version of this is private to avoid internal uses of mkVar() from
362 * within CVC4. Such uses should employ mkSkolem() instead.
364 Node
mkVar(const std::string
& name
, const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
365 Node
* mkVarPtr(const std::string
& name
, const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
367 /** Create a variable with the given type. */
368 Node
mkVar(const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
369 Node
* mkVarPtr(const TypeNode
& type
, uint32_t flags
= ExprManager::VAR_FLAG_NONE
);
373 explicit NodeManager(ExprManager
* exprManager
);
374 explicit NodeManager(ExprManager
* exprManager
, const Options
& options
);
377 /** The node manager in the current public-facing CVC4 library context */
378 static NodeManager
* currentNM() { return s_current
; }
379 /** The resource manager associated with the current node manager */
380 static ResourceManager
* currentResourceManager() { return s_current
->d_resourceManager
; }
382 /** Get this node manager's options (const version) */
383 const Options
& getOptions() const {
387 /** Get this node manager's options (non-const version) */
388 Options
& getOptions() {
392 /** Get this node manager's resource manager */
393 ResourceManager
* getResourceManager() { return d_resourceManager
; }
395 /** Get this node manager's statistics registry */
396 StatisticsRegistry
* getStatisticsRegistry() const
398 return d_statisticsRegistry
;
401 /** Subscribe to NodeManager events */
402 void subscribeEvents(NodeManagerListener
* listener
) {
403 Assert(std::find(d_listeners
.begin(), d_listeners
.end(), listener
) == d_listeners
.end(), "listener already subscribed");
404 d_listeners
.push_back(listener
);
407 /** Unsubscribe from NodeManager events */
408 void unsubscribeEvents(NodeManagerListener
* listener
) {
409 std::vector
<NodeManagerListener
*>::iterator elt
= std::find(d_listeners
.begin(), d_listeners
.end(), listener
);
410 Assert(elt
!= d_listeners
.end(), "listener not subscribed");
411 d_listeners
.erase(elt
);
414 /** register datatype */
415 unsigned registerDatatype(Datatype
* dt
);
416 /** get datatype for index */
417 const Datatype
& getDatatypeForIndex( unsigned index
) const;
419 /** Get a Kind from an operator expression */
420 static inline Kind
operatorToKind(TNode n
);
422 // general expression-builders
424 /** Create a node with one child. */
425 Node
mkNode(Kind kind
, TNode child1
);
426 Node
* mkNodePtr(Kind kind
, TNode child1
);
428 /** Create a node with two children. */
429 Node
mkNode(Kind kind
, TNode child1
, TNode child2
);
430 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
);
432 /** Create a node with three children. */
433 Node
mkNode(Kind kind
, TNode child1
, TNode child2
, TNode child3
);
434 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
, TNode child3
);
436 /** Create a node with four children. */
437 Node
mkNode(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
439 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
442 /** Create a node with five children. */
443 Node
mkNode(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
444 TNode child4
, TNode child5
);
445 Node
* mkNodePtr(Kind kind
, TNode child1
, TNode child2
, TNode child3
,
446 TNode child4
, TNode child5
);
448 /** Create a node with an arbitrary number of children. */
449 template <bool ref_count
>
450 Node
mkNode(Kind kind
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
451 template <bool ref_count
>
452 Node
* mkNodePtr(Kind kind
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
454 /** Create a node (with no children) by operator. */
455 Node
mkNode(TNode opNode
);
456 Node
* mkNodePtr(TNode opNode
);
458 /** Create a node with one child by operator. */
459 Node
mkNode(TNode opNode
, TNode child1
);
460 Node
* mkNodePtr(TNode opNode
, TNode child1
);
462 /** Create a node with two children by operator. */
463 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
);
464 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
);
466 /** Create a node with three children by operator. */
467 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
, TNode child3
);
468 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
, TNode child3
);
470 /** Create a node with four children by operator. */
471 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
473 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
476 /** Create a node with five children by operator. */
477 Node
mkNode(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
478 TNode child4
, TNode child5
);
479 Node
* mkNodePtr(TNode opNode
, TNode child1
, TNode child2
, TNode child3
,
480 TNode child4
, TNode child5
);
482 /** Create a node by applying an operator to the children. */
483 template <bool ref_count
>
484 Node
mkNode(TNode opNode
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
485 template <bool ref_count
>
486 Node
* mkNodePtr(TNode opNode
, const std::vector
<NodeTemplate
<ref_count
> >& children
);
488 Node
mkBoundVar(const std::string
& name
, const TypeNode
& type
);
489 Node
* mkBoundVarPtr(const std::string
& name
, const TypeNode
& type
);
491 Node
mkBoundVar(const TypeNode
& type
);
492 Node
* mkBoundVarPtr(const TypeNode
& type
);
494 /** get the canonical bound variable list for function type tn */
495 static Node
getBoundVarListForFunctionType( TypeNode tn
);
498 * Optional flags used to control behavior of NodeManager::mkSkolem().
499 * They should be composed with a bitwise OR (e.g.,
500 * "SKOLEM_NO_NOTIFY | SKOLEM_EXACT_NAME"). Of course, SKOLEM_DEFAULT
501 * cannot be composed in such a manner.
504 SKOLEM_DEFAULT
= 0, /**< default behavior */
505 SKOLEM_NO_NOTIFY
= 1, /**< do not notify subscribers */
506 SKOLEM_EXACT_NAME
= 2,/**< do not make the name unique by adding the id */
507 SKOLEM_IS_GLOBAL
= 4 /**< global vars appear in models even after a pop */
508 };/* enum SkolemFlags */
511 * Create a skolem constant with the given name, type, and comment.
513 * @param prefix the name of the new skolem variable is the prefix
514 * appended with a unique ID. This way a family of skolem variables
515 * can be made with unique identifiers, used in dump, tracing, and
516 * debugging output. Use SKOLEM_EXECT_NAME flag if you don't want
517 * a unique ID appended and use prefix as the name.
519 * @param type the type of the skolem variable to create
521 * @param comment a comment for dumping output; if declarations are
522 * being dumped, this is included in a comment before the declaration
523 * and can be quite useful for debugging
525 * @param flags an optional mask of bits from SkolemFlags to control
526 * mkSkolem() behavior
528 Node
mkSkolem(const std::string
& prefix
, const TypeNode
& type
,
529 const std::string
& comment
= "", int flags
= SKOLEM_DEFAULT
);
531 /** Create a instantiation constant with the given type. */
532 Node
mkInstConstant(const TypeNode
& type
);
534 /** Create a boolean term variable. */
535 Node
mkBooleanTermVariable();
537 /** Make a new abstract value with the given type. */
538 Node
mkAbstractValue(const TypeNode
& type
);
540 /** make unique (per Type,Kind) variable. */
541 Node
mkNullaryOperator(const TypeNode
& type
, Kind k
);
544 * Create a constant of type T. It will have the appropriate
545 * CONST_* kind defined for T.
548 Node
mkConst(const T
&);
551 TypeNode
mkTypeConst(const T
&);
553 template <class NodeClass
, class T
>
554 NodeClass
mkConstInternal(const T
&);
556 /** Create a node with children. */
557 TypeNode
mkTypeNode(Kind kind
, TypeNode child1
);
558 TypeNode
mkTypeNode(Kind kind
, TypeNode child1
, TypeNode child2
);
559 TypeNode
mkTypeNode(Kind kind
, TypeNode child1
, TypeNode child2
,
561 TypeNode
mkTypeNode(Kind kind
, const std::vector
<TypeNode
>& children
);
564 * Determine whether Nodes of a particular Kind have operators.
565 * @returns true if Nodes of Kind k have operators.
567 static inline bool hasOperator(Kind k
);
570 * Get the (singleton) operator of an OPERATOR-kinded kind. The
571 * returned node n will have kind BUILTIN, and calling
572 * n.getConst<CVC4::Kind>() will yield k.
574 inline TNode
operatorOf(Kind k
) {
575 AssertArgument( kind::metaKindOf(k
) == kind::metakind::OPERATOR
, k
,
576 "Kind is not an OPERATOR-kinded kind "
577 "in NodeManager::operatorOf()" );
578 return d_operators
[k
];
582 * Retrieve an attribute for a node.
584 * @param nv the node value
585 * @param attr an instance of the attribute kind to retrieve.
586 * @returns the attribute, if set, or a default-constructed
587 * <code>AttrKind::value_type</code> if not.
589 template <class AttrKind
>
590 inline typename
AttrKind::value_type
getAttribute(expr::NodeValue
* nv
,
591 const AttrKind
& attr
) const;
594 * Check whether an attribute is set for a node.
596 * @param nv the node value
597 * @param attr an instance of the attribute kind to check
598 * @returns <code>true</code> iff <code>attr</code> is set for
601 template <class AttrKind
>
602 inline bool hasAttribute(expr::NodeValue
* nv
,
603 const AttrKind
& attr
) const;
606 * Check whether an attribute is set for a node, and, if so,
609 * @param nv the node value
610 * @param attr an instance of the attribute kind to check
611 * @param value a reference to an object of the attribute's value type.
612 * <code>value</code> will be set to the value of the attribute, if it is
613 * set for <code>nv</code>; otherwise, it will be set to the default
614 * value of the attribute.
615 * @returns <code>true</code> iff <code>attr</code> is set for
618 template <class AttrKind
>
619 inline bool getAttribute(expr::NodeValue
* nv
,
620 const AttrKind
& attr
,
621 typename
AttrKind::value_type
& value
) const;
624 * Set an attribute for a node. If the node doesn't have the
625 * attribute, this function assigns one. If the node has one, this
628 * @param nv the node value
629 * @param attr an instance of the attribute kind to set
630 * @param value the value of <code>attr</code> for <code>nv</code>
632 template <class AttrKind
>
633 inline void setAttribute(expr::NodeValue
* nv
,
634 const AttrKind
& attr
,
635 const typename
AttrKind::value_type
& value
);
638 * Retrieve an attribute for a TNode.
641 * @param attr an instance of the attribute kind to retrieve.
642 * @returns the attribute, if set, or a default-constructed
643 * <code>AttrKind::value_type</code> if not.
645 template <class AttrKind
>
646 inline typename
AttrKind::value_type
647 getAttribute(TNode n
, const AttrKind
& attr
) const;
650 * Check whether an attribute is set for a TNode.
653 * @param attr an instance of the attribute kind to check
654 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
656 template <class AttrKind
>
657 inline bool hasAttribute(TNode n
,
658 const AttrKind
& attr
) const;
661 * Check whether an attribute is set for a TNode and, if so, retieve
665 * @param attr an instance of the attribute kind to check
666 * @param value a reference to an object of the attribute's value type.
667 * <code>value</code> will be set to the value of the attribute, if it is
668 * set for <code>nv</code>; otherwise, it will be set to the default value of
670 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
672 template <class AttrKind
>
673 inline bool getAttribute(TNode n
,
674 const AttrKind
& attr
,
675 typename
AttrKind::value_type
& value
) const;
678 * Set an attribute for a node. If the node doesn't have the
679 * attribute, this function assigns one. If the node has one, this
683 * @param attr an instance of the attribute kind to set
684 * @param value the value of <code>attr</code> for <code>n</code>
686 template <class AttrKind
>
687 inline void setAttribute(TNode n
,
688 const AttrKind
& attr
,
689 const typename
AttrKind::value_type
& value
);
692 * Retrieve an attribute for a TypeNode.
694 * @param n the type node
695 * @param attr an instance of the attribute kind to retrieve.
696 * @returns the attribute, if set, or a default-constructed
697 * <code>AttrKind::value_type</code> if not.
699 template <class AttrKind
>
700 inline typename
AttrKind::value_type
701 getAttribute(TypeNode n
, const AttrKind
& attr
) const;
704 * Check whether an attribute is set for a TypeNode.
706 * @param n the type node
707 * @param attr an instance of the attribute kind to check
708 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
710 template <class AttrKind
>
711 inline bool hasAttribute(TypeNode n
,
712 const AttrKind
& attr
) const;
715 * Check whether an attribute is set for a TypeNode and, if so, retieve
718 * @param n the type node
719 * @param attr an instance of the attribute kind to check
720 * @param value a reference to an object of the attribute's value type.
721 * <code>value</code> will be set to the value of the attribute, if it is
722 * set for <code>nv</code>; otherwise, it will be set to the default value of
724 * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
726 template <class AttrKind
>
727 inline bool getAttribute(TypeNode n
,
728 const AttrKind
& attr
,
729 typename
AttrKind::value_type
& value
) const;
732 * Set an attribute for a type node. If the node doesn't have the
733 * attribute, this function assigns one. If the type node has one,
734 * this overwrites it.
736 * @param n the type node
737 * @param attr an instance of the attribute kind to set
738 * @param value the value of <code>attr</code> for <code>n</code>
740 template <class AttrKind
>
741 inline void setAttribute(TypeNode n
,
742 const AttrKind
& attr
,
743 const typename
AttrKind::value_type
& value
);
745 /** Get the (singleton) type for Booleans. */
746 inline TypeNode
booleanType();
748 /** Get the (singleton) type for integers. */
749 inline TypeNode
integerType();
751 /** Get the (singleton) type for reals. */
752 inline TypeNode
realType();
754 /** Get the (singleton) type for strings. */
755 inline TypeNode
stringType();
757 /** Get the (singleton) type for RegExp. */
758 inline TypeNode
regExpType();
760 /** Get the (singleton) type for rounding modes. */
761 inline TypeNode
roundingModeType();
763 /** Get the bound var list type. */
764 inline TypeNode
boundVarListType();
766 /** Get the instantiation pattern type. */
767 inline TypeNode
instPatternType();
769 /** Get the instantiation pattern type. */
770 inline TypeNode
instPatternListType();
773 * Get the (singleton) type for builtin operators (that is, the type
774 * of the Node returned from Node::getOperator() when the operator
775 * is built-in, like EQUAL). */
776 inline TypeNode
builtinOperatorType();
779 * Make a function type from domain to range.
781 * @param domain the domain type
782 * @param range the range type
783 * @returns the functional type domain -> range
785 inline TypeNode
mkFunctionType(const TypeNode
& domain
, const TypeNode
& range
);
788 * Make a function type with input types from
789 * argTypes. <code>argTypes</code> must have at least one element.
791 * @param argTypes the domain is a tuple (argTypes[0], ..., argTypes[n])
792 * @param range the range type
793 * @returns the functional type (argTypes[0], ..., argTypes[n]) -> range
795 inline TypeNode
mkFunctionType(const std::vector
<TypeNode
>& argTypes
,
796 const TypeNode
& range
);
799 * Make a function type with input types from
800 * <code>sorts[0..sorts.size()-2]</code> and result type
801 * <code>sorts[sorts.size()-1]</code>. <code>sorts</code> must have
802 * at least 2 elements.
804 inline TypeNode
mkFunctionType(const std::vector
<TypeNode
>& sorts
);
807 * Make a predicate type with input types from
808 * <code>sorts</code>. The result with be a function type with range
809 * <code>BOOLEAN</code>. <code>sorts</code> must have at least one
812 inline TypeNode
mkPredicateType(const std::vector
<TypeNode
>& sorts
);
815 * Make a tuple type with types from
816 * <code>types</code>. <code>types</code> must have at least one
819 * @param types a vector of types
820 * @returns the tuple type (types[0], ..., types[n])
822 TypeNode
mkTupleType(const std::vector
<TypeNode
>& types
);
825 * Make a record type with the description from rec.
827 * @param rec a description of the record
828 * @returns the record type
830 TypeNode
mkRecordType(const Record
& rec
);
833 * Make a symbolic expression type with types from
834 * <code>types</code>. <code>types</code> may have any number of
837 * @param types a vector of types
838 * @returns the symbolic expression type (types[0], ..., types[n])
840 inline TypeNode
mkSExprType(const std::vector
<TypeNode
>& types
);
842 /** Make the type of floating-point with <code>exp</code> bit exponent and
843 <code>sig</code> bit significand */
844 inline TypeNode
mkFloatingPointType(unsigned exp
, unsigned sig
);
845 inline TypeNode
mkFloatingPointType(FloatingPointSize fs
);
847 /** Make the type of bitvectors of size <code>size</code> */
848 inline TypeNode
mkBitVectorType(unsigned size
);
850 /** Make the type of arrays with the given parameterization */
851 inline TypeNode
mkArrayType(TypeNode indexType
, TypeNode constituentType
);
853 /** Make the type of arrays with the given parameterization */
854 inline TypeNode
mkSetType(TypeNode elementType
);
856 /** Make a type representing a constructor with the given parameterization */
857 TypeNode
mkConstructorType(const DatatypeConstructor
& constructor
, TypeNode range
);
859 /** Make a type representing a selector with the given parameterization */
860 inline TypeNode
mkSelectorType(TypeNode domain
, TypeNode range
);
862 /** Make a type representing a tester with given parameterization */
863 inline TypeNode
mkTesterType(TypeNode domain
);
865 /** Make a new (anonymous) sort of arity 0. */
866 TypeNode
mkSort(uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
868 /** Make a new sort with the given name of arity 0. */
869 TypeNode
mkSort(const std::string
& name
, uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
871 /** Make a new sort by parameterizing the given sort constructor. */
872 TypeNode
mkSort(TypeNode constructor
,
873 const std::vector
<TypeNode
>& children
,
874 uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
876 /** Make a new sort with the given name and arity. */
877 TypeNode
mkSortConstructor(const std::string
& name
,
879 uint32_t flags
= ExprManager::SORT_FLAG_NONE
);
882 * Get the type for the given node and optionally do type checking.
884 * Initial type computation will be near-constant time if
885 * type checking is not requested. Results are memoized, so that
886 * subsequent calls to getType() without type checking will be
889 * Initial type checking is linear in the size of the expression.
890 * Again, the results are memoized, so that subsequent calls to
891 * getType(), with or without type checking, will be constant
894 * NOTE: A TypeCheckingException can be thrown even when type
895 * checking is not requested. getType() will always return a
896 * valid and correct type and, thus, an exception will be thrown
897 * when no valid or correct type can be computed (e.g., if the
898 * arguments to a bit-vector operation aren't bit-vectors). When
899 * type checking is not requested, getType() will do the minimum
900 * amount of checking required to return a valid result.
902 * @param n the Node for which we want a type
903 * @param check whether we should check the type as we compute it
906 TypeNode
getType(TNode n
, bool check
= false);
909 * Convert a node to an expression. Uses the ExprManager
910 * associated to this NodeManager.
912 inline Expr
toExpr(TNode n
);
915 * Convert an expression to a node.
917 static inline Node
fromExpr(const Expr
& e
);
920 * Convert a node manager to an expression manager.
922 inline ExprManager
* toExprManager();
925 * Convert an expression manager to a node manager.
927 static inline NodeManager
* fromExprManager(ExprManager
* exprManager
);
930 * Convert a type node to a type.
932 inline Type
toType(TypeNode tn
);
935 * Convert a type to a type node.
937 static inline TypeNode
fromType(Type t
);
939 /** Reclaim zombies while there are more than k nodes in the pool (if possible).*/
940 void reclaimZombiesUntil(uint32_t k
);
942 /** Reclaims all zombies (if possible).*/
943 void reclaimAllZombies();
945 /** Size of the node pool. */
946 size_t poolSize() const;
948 /** Deletes a list of attributes from the NM's AttributeManager.*/
949 void deleteAttributes(const std::vector
< const expr::attr::AttributeUniqueId
* >& ids
);
952 * This function gives developers a hook into the NodeManager.
953 * This can be changed in node_manager.cpp without recompiling most of cvc4.
955 * debugHook is a debugging only function, and should not be present in
956 * any published code!
958 void debugHook(int debugFlag
);
959 };/* class NodeManager */
962 * This class changes the "current" thread-global
963 * <code>NodeManager</code> when it is created and reinstates the
964 * previous thread-global <code>NodeManager</code> when it is
965 * destroyed, effectively maintaining a set of nested
966 * <code>NodeManager</code> scopes. This is especially useful on
967 * public-interface calls into the CVC4 library, where CVC4's notion
968 * of the "current" <code>NodeManager</code> should be set to match
969 * the calling context. See, for example, the implementations of
970 * public calls in the <code>ExprManager</code> and
971 * <code>SmtEngine</code> classes.
973 * The client must be careful to create and destroy
974 * <code>NodeManagerScope</code> objects in a well-nested manner (such
975 * as on the stack). You may create a <code>NodeManagerScope</code>
976 * with <code>new</code> and destroy it with <code>delete</code>, or
977 * place it as a data member of an object that is, but if the scope of
978 * these <code>new</code>/<code>delete</code> pairs isn't properly
979 * maintained, the incorrect "current" <code>NodeManager</code>
980 * pointer may be restored after a delete.
982 class NodeManagerScope
{
983 /** The old NodeManager, to be restored on destruction. */
984 NodeManager
* d_oldNodeManager
;
985 Options::OptionsScope d_optionsScope
;
988 NodeManagerScope(NodeManager
* nm
)
989 : d_oldNodeManager(NodeManager::s_current
)
990 , d_optionsScope(nm
? nm
->d_options
: NULL
) {
991 // There are corner cases where nm can be NULL and it's ok.
992 // For example, if you write { Expr e; }, then when the null
993 // Expr is destructed, there's no active node manager.
994 //Assert(nm != NULL);
995 NodeManager::s_current
= nm
;
996 //Options::s_current = nm ? nm->d_options : NULL;
997 Debug("current") << "node manager scope: "
998 << NodeManager::s_current
<< "\n";
1001 ~NodeManagerScope() {
1002 NodeManager::s_current
= d_oldNodeManager
;
1003 //Options::s_current = d_oldNodeManager ? d_oldNodeManager->d_options : NULL;
1004 Debug("current") << "node manager scope: "
1005 << "returning to " << NodeManager::s_current
<< "\n";
1007 };/* class NodeManagerScope */
1009 /** Get the (singleton) type for booleans. */
1010 inline TypeNode
NodeManager::booleanType() {
1011 return TypeNode(mkTypeConst
<TypeConstant
>(BOOLEAN_TYPE
));
1014 /** Get the (singleton) type for integers. */
1015 inline TypeNode
NodeManager::integerType() {
1016 return TypeNode(mkTypeConst
<TypeConstant
>(INTEGER_TYPE
));
1019 /** Get the (singleton) type for reals. */
1020 inline TypeNode
NodeManager::realType() {
1021 return TypeNode(mkTypeConst
<TypeConstant
>(REAL_TYPE
));
1024 /** Get the (singleton) type for strings. */
1025 inline TypeNode
NodeManager::stringType() {
1026 return TypeNode(mkTypeConst
<TypeConstant
>(STRING_TYPE
));
1029 /** Get the (singleton) type for regexps. */
1030 inline TypeNode
NodeManager::regExpType() {
1031 return TypeNode(mkTypeConst
<TypeConstant
>(REGEXP_TYPE
));
1034 /** Get the (singleton) type for rounding modes. */
1035 inline TypeNode
NodeManager::roundingModeType() {
1036 return TypeNode(mkTypeConst
<TypeConstant
>(ROUNDINGMODE_TYPE
));
1039 /** Get the bound var list type. */
1040 inline TypeNode
NodeManager::boundVarListType() {
1041 return TypeNode(mkTypeConst
<TypeConstant
>(BOUND_VAR_LIST_TYPE
));
1044 /** Get the instantiation pattern type. */
1045 inline TypeNode
NodeManager::instPatternType() {
1046 return TypeNode(mkTypeConst
<TypeConstant
>(INST_PATTERN_TYPE
));
1049 /** Get the instantiation pattern type. */
1050 inline TypeNode
NodeManager::instPatternListType() {
1051 return TypeNode(mkTypeConst
<TypeConstant
>(INST_PATTERN_LIST_TYPE
));
1054 /** Get the (singleton) type for builtin operators. */
1055 inline TypeNode
NodeManager::builtinOperatorType() {
1056 return TypeNode(mkTypeConst
<TypeConstant
>(BUILTIN_OPERATOR_TYPE
));
1059 /** Make a function type from domain to range. */
1060 inline TypeNode
NodeManager::mkFunctionType(const TypeNode
& domain
, const TypeNode
& range
) {
1061 std::vector
<TypeNode
> sorts
;
1062 sorts
.push_back(domain
);
1063 sorts
.push_back(range
);
1064 return mkFunctionType(sorts
);
1067 inline TypeNode
NodeManager::mkFunctionType(const std::vector
<TypeNode
>& argTypes
, const TypeNode
& range
) {
1068 Assert(argTypes
.size() >= 1);
1069 std::vector
<TypeNode
> sorts(argTypes
);
1070 sorts
.push_back(range
);
1071 return mkFunctionType(sorts
);
1075 NodeManager::mkFunctionType(const std::vector
<TypeNode
>& sorts
) {
1076 Assert(sorts
.size() >= 2);
1077 std::vector
<TypeNode
> sortNodes
;
1078 for (unsigned i
= 0; i
< sorts
.size(); ++ i
) {
1079 CheckArgument(sorts
[i
].isFirstClass(), sorts
,
1080 "cannot create function types for argument types that are not first-class");
1081 sortNodes
.push_back(sorts
[i
]);
1083 CheckArgument(!sorts
[sorts
.size()-1].isFunction(), sorts
[sorts
.size()-1],
1084 "must flatten function types");
1085 return mkTypeNode(kind::FUNCTION_TYPE
, sortNodes
);
1089 NodeManager::mkPredicateType(const std::vector
<TypeNode
>& sorts
) {
1090 Assert(sorts
.size() >= 1);
1091 std::vector
<TypeNode
> sortNodes
;
1092 for (unsigned i
= 0; i
< sorts
.size(); ++ i
) {
1093 CheckArgument(sorts
[i
].isFirstClass(), sorts
,
1094 "cannot create predicate types for argument types that are not first-class");
1095 sortNodes
.push_back(sorts
[i
]);
1097 sortNodes
.push_back(booleanType());
1098 return mkTypeNode(kind::FUNCTION_TYPE
, sortNodes
);
1101 inline TypeNode
NodeManager::mkSExprType(const std::vector
<TypeNode
>& types
) {
1102 std::vector
<TypeNode
> typeNodes
;
1103 for (unsigned i
= 0; i
< types
.size(); ++ i
) {
1104 typeNodes
.push_back(types
[i
]);
1106 return mkTypeNode(kind::SEXPR_TYPE
, typeNodes
);
1109 inline TypeNode
NodeManager::mkBitVectorType(unsigned size
) {
1110 return TypeNode(mkTypeConst
<BitVectorSize
>(BitVectorSize(size
)));
1113 inline TypeNode
NodeManager::mkFloatingPointType(unsigned exp
, unsigned sig
) {
1114 return TypeNode(mkTypeConst
<FloatingPointSize
>(FloatingPointSize(exp
,sig
)));
1117 inline TypeNode
NodeManager::mkFloatingPointType(FloatingPointSize fs
) {
1118 return TypeNode(mkTypeConst
<FloatingPointSize
>(fs
));
1121 inline TypeNode
NodeManager::mkArrayType(TypeNode indexType
,
1122 TypeNode constituentType
) {
1123 CheckArgument(!indexType
.isNull(), indexType
,
1124 "unexpected NULL index type");
1125 CheckArgument(!constituentType
.isNull(), constituentType
,
1126 "unexpected NULL constituent type");
1127 CheckArgument(indexType
.isFirstClass(), indexType
,
1128 "cannot index arrays by types that are not first-class");
1129 CheckArgument(constituentType
.isFirstClass(), constituentType
,
1130 "cannot store types that are not first-class in arrays");
1131 Debug("arrays") << "making array type " << indexType
<< " "
1132 << constituentType
<< std::endl
;
1133 return mkTypeNode(kind::ARRAY_TYPE
, indexType
, constituentType
);
1136 inline TypeNode
NodeManager::mkSetType(TypeNode elementType
) {
1137 CheckArgument(!elementType
.isNull(), elementType
,
1138 "unexpected NULL element type");
1139 CheckArgument(elementType
.isFirstClass(), elementType
,
1140 "cannot store types that are not first-class in sets");
1141 Debug("sets") << "making sets type " << elementType
<< std::endl
;
1142 return mkTypeNode(kind::SET_TYPE
, elementType
);
1145 inline TypeNode
NodeManager::mkSelectorType(TypeNode domain
, TypeNode range
) {
1146 CheckArgument(domain
.isDatatype(), domain
,
1147 "cannot create non-datatype selector type");
1148 CheckArgument(range
.isFirstClass(), range
,
1149 "cannot have selector fields that are not first-class types");
1150 return mkTypeNode(kind::SELECTOR_TYPE
, domain
, range
);
1153 inline TypeNode
NodeManager::mkTesterType(TypeNode domain
) {
1154 CheckArgument(domain
.isDatatype(), domain
,
1155 "cannot create non-datatype tester");
1156 return mkTypeNode(kind::TESTER_TYPE
, domain
);
1159 inline expr::NodeValue
* NodeManager::poolLookup(expr::NodeValue
* nv
) const {
1160 NodeValuePool::const_iterator find
= d_nodeValuePool
.find(nv
);
1161 if(find
== d_nodeValuePool
.end()) {
1168 inline void NodeManager::poolInsert(expr::NodeValue
* nv
) {
1169 Assert(d_nodeValuePool
.find(nv
) == d_nodeValuePool
.end(),
1170 "NodeValue already in the pool!");
1171 d_nodeValuePool
.insert(nv
);// FIXME multithreading
1174 inline void NodeManager::poolRemove(expr::NodeValue
* nv
) {
1175 Assert(d_nodeValuePool
.find(nv
) != d_nodeValuePool
.end(),
1176 "NodeValue is not in the pool!");
1178 d_nodeValuePool
.erase(nv
);// FIXME multithreading
1181 inline Expr
NodeManager::toExpr(TNode n
) {
1182 return Expr(d_exprManager
, new Node(n
));
1185 inline Node
NodeManager::fromExpr(const Expr
& e
) {
1189 inline ExprManager
* NodeManager::toExprManager() {
1190 return d_exprManager
;
1193 inline NodeManager
* NodeManager::fromExprManager(ExprManager
* exprManager
) {
1194 return exprManager
->getNodeManager();
1197 inline Type
NodeManager::toType(TypeNode tn
) {
1198 return Type(this, new TypeNode(tn
));
1201 inline TypeNode
NodeManager::fromType(Type t
) {
1202 return *Type::getTypeNode(t
);
1205 }/* CVC4 namespace */
1207 #define __CVC4__NODE_MANAGER_NEEDS_CONSTANT_MAP
1208 #include "expr/metakind.h"
1209 #undef __CVC4__NODE_MANAGER_NEEDS_CONSTANT_MAP
1211 #include "expr/node_builder.h"
1215 // general expression-builders
1217 inline bool NodeManager::hasOperator(Kind k
) {
1218 switch(kind::MetaKind mk
= kind::metaKindOf(k
)) {
1220 case kind::metakind::INVALID
:
1221 case kind::metakind::VARIABLE
:
1222 case kind::metakind::NULLARY_OPERATOR
:
1225 case kind::metakind::OPERATOR
:
1226 case kind::metakind::PARAMETERIZED
:
1229 case kind::metakind::CONSTANT
:
1237 inline Kind
NodeManager::operatorToKind(TNode n
) {
1238 return kind::operatorToKind(n
.d_nv
);
1241 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
) {
1242 NodeBuilder
<1> nb(this, kind
);
1244 return nb
.constructNode();
1247 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
) {
1248 NodeBuilder
<1> nb(this, kind
);
1250 return nb
.constructNodePtr();
1253 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
) {
1254 NodeBuilder
<2> nb(this, kind
);
1255 nb
<< child1
<< child2
;
1256 return nb
.constructNode();
1259 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
) {
1260 NodeBuilder
<2> nb(this, kind
);
1261 nb
<< child1
<< child2
;
1262 return nb
.constructNodePtr();
1265 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
,
1267 NodeBuilder
<3> nb(this, kind
);
1268 nb
<< child1
<< child2
<< child3
;
1269 return nb
.constructNode();
1272 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
,
1274 NodeBuilder
<3> nb(this, kind
);
1275 nb
<< child1
<< child2
<< child3
;
1276 return nb
.constructNodePtr();
1279 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
,
1280 TNode child3
, TNode child4
) {
1281 NodeBuilder
<4> nb(this, kind
);
1282 nb
<< child1
<< child2
<< child3
<< child4
;
1283 return nb
.constructNode();
1286 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
,
1287 TNode child3
, TNode child4
) {
1288 NodeBuilder
<4> nb(this, kind
);
1289 nb
<< child1
<< child2
<< child3
<< child4
;
1290 return nb
.constructNodePtr();
1293 inline Node
NodeManager::mkNode(Kind kind
, TNode child1
, TNode child2
,
1294 TNode child3
, TNode child4
, TNode child5
) {
1295 NodeBuilder
<5> nb(this, kind
);
1296 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1297 return nb
.constructNode();
1300 inline Node
* NodeManager::mkNodePtr(Kind kind
, TNode child1
, TNode child2
,
1301 TNode child3
, TNode child4
, TNode child5
) {
1302 NodeBuilder
<5> nb(this, kind
);
1303 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1304 return nb
.constructNodePtr();
1308 template <bool ref_count
>
1309 inline Node
NodeManager::mkNode(Kind kind
,
1310 const std::vector
<NodeTemplate
<ref_count
> >&
1312 NodeBuilder
<> nb(this, kind
);
1313 nb
.append(children
);
1314 return nb
.constructNode();
1317 template <bool ref_count
>
1318 inline Node
* NodeManager::mkNodePtr(Kind kind
,
1319 const std::vector
<NodeTemplate
<ref_count
> >&
1321 NodeBuilder
<> nb(this, kind
);
1322 nb
.append(children
);
1323 return nb
.constructNodePtr();
1327 inline Node
NodeManager::mkNode(TNode opNode
) {
1328 NodeBuilder
<1> nb(this, operatorToKind(opNode
));
1329 if(opNode
.getKind() != kind::BUILTIN
) {
1332 return nb
.constructNode();
1335 inline Node
* NodeManager::mkNodePtr(TNode opNode
) {
1336 NodeBuilder
<1> nb(this, operatorToKind(opNode
));
1337 if(opNode
.getKind() != kind::BUILTIN
) {
1340 return nb
.constructNodePtr();
1343 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
) {
1344 NodeBuilder
<2> nb(this, operatorToKind(opNode
));
1345 if(opNode
.getKind() != kind::BUILTIN
) {
1349 return nb
.constructNode();
1352 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
) {
1353 NodeBuilder
<2> nb(this, operatorToKind(opNode
));
1354 if(opNode
.getKind() != kind::BUILTIN
) {
1358 return nb
.constructNodePtr();
1361 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
) {
1362 NodeBuilder
<3> nb(this, operatorToKind(opNode
));
1363 if(opNode
.getKind() != kind::BUILTIN
) {
1366 nb
<< child1
<< child2
;
1367 return nb
.constructNode();
1370 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
) {
1371 NodeBuilder
<3> nb(this, operatorToKind(opNode
));
1372 if(opNode
.getKind() != kind::BUILTIN
) {
1375 nb
<< child1
<< child2
;
1376 return nb
.constructNodePtr();
1379 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
,
1381 NodeBuilder
<4> nb(this, operatorToKind(opNode
));
1382 if(opNode
.getKind() != kind::BUILTIN
) {
1385 nb
<< child1
<< child2
<< child3
;
1386 return nb
.constructNode();
1389 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
,
1391 NodeBuilder
<4> nb(this, operatorToKind(opNode
));
1392 if(opNode
.getKind() != kind::BUILTIN
) {
1395 nb
<< child1
<< child2
<< child3
;
1396 return nb
.constructNodePtr();
1399 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
,
1400 TNode child3
, TNode child4
) {
1401 NodeBuilder
<5> nb(this, operatorToKind(opNode
));
1402 if(opNode
.getKind() != kind::BUILTIN
) {
1405 nb
<< child1
<< child2
<< child3
<< child4
;
1406 return nb
.constructNode();
1409 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
,
1410 TNode child3
, TNode child4
) {
1411 NodeBuilder
<5> nb(this, operatorToKind(opNode
));
1412 if(opNode
.getKind() != kind::BUILTIN
) {
1415 nb
<< child1
<< child2
<< child3
<< child4
;
1416 return nb
.constructNodePtr();
1419 inline Node
NodeManager::mkNode(TNode opNode
, TNode child1
, TNode child2
,
1420 TNode child3
, TNode child4
, TNode child5
) {
1421 NodeBuilder
<6> nb(this, operatorToKind(opNode
));
1422 if(opNode
.getKind() != kind::BUILTIN
) {
1425 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1426 return nb
.constructNode();
1429 inline Node
* NodeManager::mkNodePtr(TNode opNode
, TNode child1
, TNode child2
,
1430 TNode child3
, TNode child4
, TNode child5
) {
1431 NodeBuilder
<6> nb(this, operatorToKind(opNode
));
1432 if(opNode
.getKind() != kind::BUILTIN
) {
1435 nb
<< child1
<< child2
<< child3
<< child4
<< child5
;
1436 return nb
.constructNodePtr();
1439 // N-ary version for operators
1440 template <bool ref_count
>
1441 inline Node
NodeManager::mkNode(TNode opNode
,
1442 const std::vector
<NodeTemplate
<ref_count
> >&
1444 NodeBuilder
<> nb(this, operatorToKind(opNode
));
1445 if(opNode
.getKind() != kind::BUILTIN
) {
1448 nb
.append(children
);
1449 return nb
.constructNode();
1452 template <bool ref_count
>
1453 inline Node
* NodeManager::mkNodePtr(TNode opNode
,
1454 const std::vector
<NodeTemplate
<ref_count
> >&
1456 NodeBuilder
<> nb(this, operatorToKind(opNode
));
1457 if(opNode
.getKind() != kind::BUILTIN
) {
1460 nb
.append(children
);
1461 return nb
.constructNodePtr();
1465 inline TypeNode
NodeManager::mkTypeNode(Kind kind
, TypeNode child1
) {
1466 return (NodeBuilder
<1>(this, kind
) << child1
).constructTypeNode();
1469 inline TypeNode
NodeManager::mkTypeNode(Kind kind
, TypeNode child1
,
1471 return (NodeBuilder
<2>(this, kind
) << child1
<< child2
).constructTypeNode();
1474 inline TypeNode
NodeManager::mkTypeNode(Kind kind
, TypeNode child1
,
1475 TypeNode child2
, TypeNode child3
) {
1476 return (NodeBuilder
<3>(this, kind
) << child1
<< child2
<< child3
).constructTypeNode();
1479 // N-ary version for types
1480 inline TypeNode
NodeManager::mkTypeNode(Kind kind
,
1481 const std::vector
<TypeNode
>& children
) {
1482 return NodeBuilder
<>(this, kind
).append(children
).constructTypeNode();
1486 Node
NodeManager::mkConst(const T
& val
) {
1487 return mkConstInternal
<Node
, T
>(val
);
1491 TypeNode
NodeManager::mkTypeConst(const T
& val
) {
1492 return mkConstInternal
<TypeNode
, T
>(val
);
1495 template <class NodeClass
, class T
>
1496 NodeClass
NodeManager::mkConstInternal(const T
& val
) {
1498 // typedef typename kind::metakind::constantMap<T>::OwningTheory theory_t;
1499 NVStorage
<1> nvStorage
;
1500 expr::NodeValue
& nvStack
= reinterpret_cast<expr::NodeValue
&>(nvStorage
);
1503 nvStack
.d_kind
= kind::metakind::ConstantMap
<T
>::kind
;
1505 nvStack
.d_nchildren
= 1;
1507 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1508 #pragma GCC diagnostic push
1509 #pragma GCC diagnostic ignored "-Warray-bounds"
1512 nvStack
.d_children
[0] =
1513 const_cast<expr::NodeValue
*>(reinterpret_cast<const expr::NodeValue
*>(&val
));
1514 expr::NodeValue
* nv
= poolLookup(&nvStack
);
1516 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1517 #pragma GCC diagnostic pop
1521 return NodeClass(nv
);
1524 nv
= (expr::NodeValue
*)
1525 std::malloc(sizeof(expr::NodeValue
) + sizeof(T
));
1527 throw std::bad_alloc();
1530 nv
->d_nchildren
= 0;
1531 nv
->d_kind
= kind::metakind::ConstantMap
<T
>::kind
;
1532 nv
->d_id
= next_id
++;// FIXME multithreading
1535 //OwningTheory::mkConst(val);
1536 new (&nv
->d_children
) T(val
);
1539 if(Debug
.isOn("gc")) {
1540 Debug("gc") << "creating node value " << nv
1541 << " [" << nv
->d_id
<< "]: ";
1542 nv
->printAst(Debug("gc"));
1543 Debug("gc") << std::endl
;
1546 return NodeClass(nv
);
1549 }/* CVC4 namespace */
1551 #endif /* __CVC4__NODE_MANAGER_H */