GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node_manager.h Lines: 171 196 87.2 %
Date: 2021-05-24 Branches: 528 2014 26.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Morgan Deters, Andrew Reynolds, Christopher L. Conway
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * A manager for Nodes.
14
 */
15
16
#include "cvc5_private.h"
17
18
/* circular dependency; force node.h first */
19
//#include "expr/attribute.h"
20
#include "expr/node.h"
21
#include "expr/type_node.h"
22
23
#ifndef CVC5__NODE_MANAGER_H
24
#define CVC5__NODE_MANAGER_H
25
26
#include <vector>
27
#include <string>
28
#include <unordered_set>
29
30
#include "base/check.h"
31
#include "expr/kind.h"
32
#include "expr/metakind.h"
33
#include "expr/node_value.h"
34
35
namespace cvc5 {
36
37
using Record = std::vector<std::pair<std::string, TypeNode>>;
38
39
namespace api {
40
class Solver;
41
}
42
43
class ResourceManager;
44
class SkolemManager;
45
class BoundVarManager;
46
47
class DType;
48
49
namespace expr {
50
  namespace attr {
51
    class AttributeUniqueId;
52
    class AttributeManager;
53
    }  // namespace attr
54
55
  class TypeChecker;
56
  }  // namespace expr
57
58
/**
59
 * An interface that an interested party can implement and then subscribe
60
 * to NodeManager events via NodeManager::subscribeEvents(this).
61
 */
62
19552
class NodeManagerListener {
63
 public:
64
19552
  virtual ~NodeManagerListener() {}
65
2736
  virtual void nmNotifyNewSort(TypeNode tn, uint32_t flags) {}
66
6
  virtual void nmNotifyNewSortConstructor(TypeNode tn, uint32_t flags) {}
67
629
  virtual void nmNotifyInstantiateSortConstructor(TypeNode ctor, TypeNode sort,
68
629
                                                  uint32_t flags) {}
69
1174
  virtual void nmNotifyNewDatatypes(const std::vector<TypeNode>& datatypes,
70
                                    uint32_t flags)
71
  {
72
1174
  }
73
  virtual void nmNotifyNewVar(TNode n) {}
74
  virtual void nmNotifyNewSkolem(TNode n, const std::string& comment,
75
                                 uint32_t flags) {}
76
  /**
77
   * Notify a listener of a Node that's being GCed.  If this function stores a
78
   * reference
79
   * to the Node somewhere, very bad things will happen.
80
   */
81
8237281
  virtual void nmNotifyDeleteNode(TNode n) {}
82
}; /* class NodeManagerListener */
83
84
class NodeManager
85
{
86
  friend class api::Solver;
87
  friend class expr::NodeValue;
88
  friend class expr::TypeChecker;
89
  friend class SkolemManager;
90
91
  friend class NodeBuilder;
92
  friend class NodeManagerScope;
93
94
 public:
95
  /**
96
   * Return true if given kind is n-ary. The test is based on n-ary kinds
97
   * having their maximal arity as the maximal possible number of children
98
   * of a node.
99
   */
100
  static bool isNAryKind(Kind k);
101
102
 private:
103
  /** Predicate for use with STL algorithms */
104
  struct NodeValueReferenceCountNonZero {
105
29916800
    bool operator()(expr::NodeValue* nv) { return nv->d_rc > 0; }
106
  };
107
108
  typedef std::unordered_set<expr::NodeValue*,
109
                             expr::NodeValuePoolHashFunction,
110
                             expr::NodeValuePoolEq> NodeValuePool;
111
  typedef std::unordered_set<expr::NodeValue*,
112
                             expr::NodeValueIDHashFunction,
113
                             expr::NodeValueIDEquality> NodeValueIDSet;
114
115
  static thread_local NodeManager* s_current;
116
117
  /** The skolem manager */
118
  std::unique_ptr<SkolemManager> d_skManager;
119
  /** The bound variable manager */
120
  std::unique_ptr<BoundVarManager> d_bvManager;
121
122
  NodeValuePool d_nodeValuePool;
123
124
  size_t next_id;
125
126
  expr::attr::AttributeManager* d_attrManager;
127
128
  /**
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.
135
   */
136
  expr::NodeValue* d_nodeUnderDeletion;
137
138
  /**
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
142
   * reclaimZombies().
143
   */
144
  bool d_inReclaimZombies;
145
146
  /**
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.
150
   */
151
  NodeValueIDSet d_zombies;
152
153
  /**
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.
156
   */
157
  std::vector<expr::NodeValue*> d_maxedOut;
158
159
  /**
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<cvc5::Kind>(), you get kind::PLUS back.
166
   */
167
  Node d_operators[kind::LAST_KIND];
168
169
  /** unique vars per (Kind,Type) */
170
  std::map< Kind, std::map< TypeNode, Node > > d_unique_vars;
171
172
  /**
173
   * A list of subscribers for NodeManager events.
174
   */
175
  std::vector<NodeManagerListener*> d_listeners;
176
177
  /** A list of datatypes owned by this node manager */
178
  std::vector<std::unique_ptr<DType> > d_dtypes;
179
180
  /**
181
   * A map of tuple and record types to their corresponding datatype.
182
   */
183
17074
  class TupleTypeCache {
184
  public:
185
    std::map< TypeNode, TupleTypeCache > d_children;
186
    TypeNode d_data;
187
    TypeNode getTupleType( NodeManager * nm, std::vector< TypeNode >& types, unsigned index = 0 );
188
  };
189
15588
  class RecTypeCache {
190
  public:
191
    std::map< TypeNode, std::map< std::string, RecTypeCache > > d_children;
192
    TypeNode d_data;
193
    TypeNode getRecordType( NodeManager * nm, const Record& rec, unsigned index = 0 );
194
  };
195
  TupleTypeCache d_tt_cache;
196
  RecTypeCache d_rt_cache;
197
198
  /**
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
202
   * values to overlap.
203
   */
204
  unsigned d_abstractValueCount;
205
206
  /**
207
   * A counter used to produce unique skolem names.
208
   *
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.
212
   */
213
  unsigned d_skolemCounter;
214
215
  /**
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
219
   * (see below).
220
   *
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.
224
   *
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
230
   * constant value.
231
   *
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!
238
   */
239
  inline expr::NodeValue* poolLookup(expr::NodeValue* nv) const;
240
241
  /**
242
   * Insert a NodeValue into the NodeManager's pool.
243
   *
244
   * It is an error to insert a NodeValue already in the pool.
245
   * Enquire first with poolLookup().
246
   */
247
  inline void poolInsert(expr::NodeValue* nv);
248
249
  /**
250
   * Remove a NodeValue from the NodeManager's pool.
251
   *
252
   * It is an error to request the removal of a NodeValue from the
253
   * pool that is not in the pool.
254
   */
255
  inline void poolRemove(expr::NodeValue* nv);
256
257
  /**
258
   * Determine if nv is currently being deleted by the NodeManager.
259
   */
260
15857821072
  inline bool isCurrentlyDeleting(const expr::NodeValue* nv) const {
261
15857821072
    return d_nodeUnderDeletion == nv;
262
  }
263
264
  /**
265
   * Register a NodeValue as a zombie.
266
   */
267
46600409
  inline void markForDeletion(expr::NodeValue* nv) {
268
46600409
    Assert(nv->d_rc == 0);
269
270
    // if d_reclaiming is set, make sure we don't call
271
    // reclaimZombies(), because it's already running.
272
46600409
    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]" : "")
277
                  << std::endl;
278
    }
279
280
    // `d_zombies` uses the node id to hash and compare nodes. If `d_zombies`
281
    // already contains a node value with the same id as `nv`, but the pointers
282
    // are different, then the wrong `NodeManager` was in scope for one of the
283
    // two nodes when it reached refcount zero.
284
46600409
    Assert(d_zombies.find(nv) == d_zombies.end() || *d_zombies.find(nv) == nv);
285
286
46600409
    d_zombies.insert(nv);
287
288
46600409
    if(safeToReclaimZombies()) {
289
31266031
      if(d_zombies.size() > 5000) {
290
2553
        reclaimZombies();
291
      }
292
    }
293
46600409
  }
294
295
  /**
296
   * Register a NodeValue as having a maxed out reference count. This NodeValue
297
   * will live as long as its containing NodeManager.
298
   */
299
7
  inline void markRefCountMaxedOut(expr::NodeValue* nv) {
300
7
    Assert(nv->HasMaximizedReferenceCount());
301
7
    if(Debug.isOn("gc")) {
302
      Debug("gc") << "marking node value " << nv
303
                  << " [" << nv->d_id << "]: as maxed out" << std::endl;
304
    }
305
7
    d_maxedOut.push_back(nv);
306
7
  }
307
308
  /**
309
   * Reclaim all zombies.
310
   */
311
  void reclaimZombies();
312
313
  /**
314
   * It is safe to collect zombies.
315
   */
316
  bool safeToReclaimZombies() const;
317
318
  /**
319
   * Returns a reverse topological sort of a list of NodeValues. The NodeValues
320
   * must be valid and have ids. The NodeValues are not modified (including ref
321
   * counts).
322
   */
323
  static std::vector<expr::NodeValue*> TopologicalSort(
324
      const std::vector<expr::NodeValue*>& roots);
325
326
  /**
327
   * This template gives a mechanism to stack-allocate a NodeValue
328
   * with enough space for N children (where N is a compile-time
329
   * constant).  You use it like this:
330
   *
331
   *   NVStorage<4> nvStorage;
332
   *   NodeValue& nvStack = reinterpret_cast<NodeValue&>(nvStorage);
333
   *
334
   * ...and then you can use nvStack as a NodeValue that you know has
335
   * room for 4 children.
336
   */
337
  template <size_t N>
338
224350182
  struct NVStorage {
339
    expr::NodeValue nv;
340
    expr::NodeValue* child[N];
341
  };/* struct NodeManager::NVStorage<N> */
342
343
  // undefined private copy constructor (disallow copy)
344
  NodeManager(const NodeManager&) = delete;
345
346
  NodeManager& operator=(const NodeManager&) = delete;
347
348
  void init();
349
350
  /**
351
   * Create a variable with the given name and type.  NOTE that no
352
   * lookup is done on the name.  If you mkVar("a", type) and then
353
   * mkVar("a", type) again, you have two variables.  The NodeManager
354
   * version of this is private to avoid internal uses of mkVar() from
355
   * within cvc5.  Such uses should employ SkolemManager::mkSkolem() instead.
356
   */
357
  Node mkVar(const std::string& name, const TypeNode& type);
358
359
  /** Create a variable with the given type. */
360
  Node mkVar(const TypeNode& type);
361
362
  /**
363
   * Create a skolem constant with the given name, type, and comment. For
364
   * details, see SkolemManager::mkDummySkolem, which calls this method.
365
   *
366
   * This method is intentionally private. To create skolems, one should
367
   * call a method from SkolemManager for allocating a skolem in a standard
368
   * way, or otherwise use SkolemManager::mkDummySkolem.
369
   */
370
  Node mkSkolem(const std::string& prefix,
371
                const TypeNode& type,
372
                const std::string& comment = "",
373
                int flags = SKOLEM_DEFAULT);
374
375
 public:
376
  explicit NodeManager();
377
  ~NodeManager();
378
379
  /** The node manager in the current public-facing cvc5 library context */
380
73083700823
  static NodeManager* currentNM() { return s_current; }
381
  /** Get this node manager's skolem manager */
382
213903
  SkolemManager* getSkolemManager() { return d_skManager.get(); }
383
  /** Get this node manager's bound variable manager */
384
727163
  BoundVarManager* getBoundVarManager() { return d_bvManager.get(); }
385
386
  /** Subscribe to NodeManager events */
387
17503
  void subscribeEvents(NodeManagerListener* listener) {
388
17503
    Assert(std::find(d_listeners.begin(), d_listeners.end(), listener)
389
           == d_listeners.end())
390
        << "listener already subscribed";
391
17503
    d_listeners.push_back(listener);
392
17503
  }
393
394
  /** Unsubscribe from NodeManager events */
395
17503
  void unsubscribeEvents(NodeManagerListener* listener) {
396
17503
    std::vector<NodeManagerListener*>::iterator elt = std::find(d_listeners.begin(), d_listeners.end(), listener);
397
17503
    Assert(elt != d_listeners.end()) << "listener not subscribed";
398
17503
    d_listeners.erase(elt);
399
17503
  }
400
401
  /**
402
   * Return the datatype at the given index owned by this class. Type nodes are
403
   * associated with datatypes through the DatatypeIndexConstant class. The
404
   * argument index is intended to be a value taken from that class.
405
   *
406
   * Type nodes must access their DTypes through a level of indirection to
407
   * prevent cycles in the Node AST (as DTypes themselves contain Nodes), which
408
   * would lead to memory leaks. Thus TypeNode are given a DatatypeIndexConstant
409
   * which is used as an index to retrieve the DType via this call.
410
   */
411
  const DType& getDTypeForIndex(size_t index) const;
412
413
  /** Get a Kind from an operator expression */
414
  static inline Kind operatorToKind(TNode n);
415
416
  /** Get corresponding application kind for function
417
   *
418
   * Different functional nodes are applied differently, according to their
419
   * type. For example, uninterpreted functions (of FUNCTION_TYPE) are applied
420
   * via APPLY_UF, while constructors (of CONSTRUCTOR_TYPE) via
421
   * APPLY_CONSTRUCTOR. This method provides the correct application according
422
   * to which functional type fun has.
423
   *
424
   * @param fun The functional node
425
   * @return the correct application kind for fun. If fun's type is not function
426
   * like (see TypeNode::isFunctionLike), then UNDEFINED_KIND is returned.
427
   */
428
  static Kind getKindForFunction(TNode fun);
429
430
  // general expression-builders
431
  //
432
  /** Create a node with no child. */
433
  Node mkNode(Kind kind);
434
435
  /** Create a node with one child. */
436
  Node mkNode(Kind kind, TNode child1);
437
438
  /** Create a node with two children. */
439
  Node mkNode(Kind kind, TNode child1, TNode child2);
440
441
  /** Create a node with three children. */
442
  Node mkNode(Kind kind, TNode child1, TNode child2, TNode child3);
443
444
  /** Create a node with an arbitrary number of children. */
445
  template <bool ref_count>
446
  Node mkNode(Kind kind, const std::vector<NodeTemplate<ref_count> >& children);
447
448
  /** Create a node using an initializer list.
449
   *
450
   * This function serves two purposes:
451
   * - We can avoid creating a temporary vector in some cases, e.g., when we
452
   *   want to create a node with a fixed, large number of children
453
   * - It makes sure that calls to `mkNode` that braced-init-lists work as
454
   *   expected, e.g., mkNode(REGEXP_EMPTY, {}) will call this overload instead
455
   *   of creating a node with a null node as a child.
456
   */
457
  Node mkNode(Kind kind, std::initializer_list<TNode> children);
458
459
  /**
460
   * Create an AND node with arbitrary number of children. This returns the
461
   * true node if children is empty, or the single node in children if
462
   * it contains only one node.
463
   *
464
   * We define construction of AND as a special case here since it is widely
465
   * used for e.g. constructing explanations.
466
   */
467
  template <bool ref_count>
468
  Node mkAnd(const std::vector<NodeTemplate<ref_count> >& children);
469
470
  /**
471
   * Create an OR node with arbitrary number of children. This returns the
472
   * false node if children is empty, or the single node in children if
473
   * it contains only one node.
474
   *
475
   * We define construction of OR as a special case here since it is widely
476
   * used for e.g. constructing explanations or lemmas.
477
   */
478
  template <bool ref_count>
479
  Node mkOr(const std::vector<NodeTemplate<ref_count> >& children);
480
481
  /** Create a node (with no children) by operator. */
482
  Node mkNode(TNode opNode);
483
484
  /** Create a node with one child by operator. */
485
  Node mkNode(TNode opNode, TNode child1);
486
487
  /** Create a node with two children by operator. */
488
  Node mkNode(TNode opNode, TNode child1, TNode child2);
489
490
  /** Create a node with three children by operator. */
491
  Node mkNode(TNode opNode, TNode child1, TNode child2, TNode child3);
492
493
  /** Create a node by applying an operator to the children. */
494
  template <bool ref_count>
495
  Node mkNode(TNode opNode, const std::vector<NodeTemplate<ref_count> >& children);
496
497
  /**
498
   * Create a node by applying an operator to an arbitrary number of children.
499
   *
500
   * Analoguous to `mkNode(Kind, std::initializer_list<TNode>)`.
501
   */
502
  Node mkNode(TNode opNode, std::initializer_list<TNode> children);
503
504
  Node mkBoundVar(const std::string& name, const TypeNode& type);
505
506
  Node mkBoundVar(const TypeNode& type);
507
508
  /** get the canonical bound variable list for function type tn */
509
  Node getBoundVarListForFunctionType( TypeNode tn );
510
511
  /**
512
   * Create an Node by applying an associative operator to the children.
513
   * If <code>children.size()</code> is greater than the max arity for
514
   * <code>kind</code>, then the expression will be broken up into
515
   * suitably-sized chunks, taking advantage of the associativity of
516
   * <code>kind</code>. For example, if kind <code>FOO</code> has max arity
517
   * 2, then calling <code>mkAssociative(FOO,a,b,c)</code> will return
518
   * <code>(FOO (FOO a b) c)</code> or <code>(FOO a (FOO b c))</code>.
519
   * The order of the arguments will be preserved in a left-to-right
520
   * traversal of the resulting tree.
521
   */
522
  Node mkAssociative(Kind kind, const std::vector<Node>& children);
523
524
  /**
525
   * Create an Node by applying an binary left-associative operator to the
526
   * children. For example, mkLeftAssociative( f, { a, b, c } ) returns
527
   * f( f( a, b ), c ).
528
   */
529
  Node mkLeftAssociative(Kind kind, const std::vector<Node>& children);
530
  /**
531
   * Create an Node by applying an binary right-associative operator to the
532
   * children. For example, mkRightAssociative( f, { a, b, c } ) returns
533
   * f( a, f( b, c ) ).
534
   */
535
  Node mkRightAssociative(Kind kind, const std::vector<Node>& children);
536
537
  /** make chain
538
   *
539
   * Given a kind k and arguments t_1, ..., t_n, this returns the
540
   * conjunction of:
541
   *  (k t_1 t_2) .... (k t_{n-1} t_n)
542
   * It is expected that k is a kind denoting a predicate, and args is a list
543
   * of terms of size >= 2 such that the terms above are well-typed.
544
   */
545
  Node mkChain(Kind kind, const std::vector<Node>& children);
546
547
  /**
548
   * Optional flags used to control behavior of NodeManager::mkSkolem().
549
   * They should be composed with a bitwise OR (e.g.,
550
   * "SKOLEM_NO_NOTIFY | SKOLEM_EXACT_NAME").  Of course, SKOLEM_DEFAULT
551
   * cannot be composed in such a manner.
552
   */
553
  enum SkolemFlags
554
  {
555
    SKOLEM_DEFAULT = 0,    /**< default behavior */
556
    SKOLEM_NO_NOTIFY = 1,  /**< do not notify subscribers */
557
    SKOLEM_EXACT_NAME = 2, /**< do not make the name unique by adding the id */
558
    SKOLEM_IS_GLOBAL = 4,  /**< global vars appear in models even after a pop */
559
    SKOLEM_BOOL_TERM_VAR = 8 /**< vars requiring kind BOOLEAN_TERM_VARIABLE */
560
  };                         /* enum SkolemFlags */
561
562
  /** Create a instantiation constant with the given type. */
563
  Node mkInstConstant(const TypeNode& type);
564
565
  /** Create a boolean term variable. */
566
  Node mkBooleanTermVariable();
567
568
  /** Make a new abstract value with the given type. */
569
  Node mkAbstractValue(const TypeNode& type);
570
571
  /** make unique (per Type,Kind) variable. */
572
  Node mkNullaryOperator(const TypeNode& type, Kind k);
573
574
  /**
575
  * Create a singleton set from the given element n.
576
  * @param t the element type of the returned set.
577
  *          Note that the type of n needs to be a subtype of t.
578
  * @param n the single element in the singleton.
579
  * @return a singleton set constructed from the element n.
580
  */
581
  Node mkSingleton(const TypeNode& t, const TNode n);
582
583
  /**
584
  * Create a bag from the given element n along with its multiplicity m.
585
  * @param t the element type of the returned bag.
586
  *          Note that the type of n needs to be a subtype of t.
587
  * @param n the element that is used to to construct the bag
588
  * @param m the multiplicity of the element n
589
  * @return a bag that contains m occurrences of n.
590
  */
591
  Node mkBag(const TypeNode& t, const TNode n, const TNode m);
592
593
  /**
594
   * Create a constant of type T.  It will have the appropriate
595
   * CONST_* kind defined for T.
596
   */
597
  template <class T>
598
  Node mkConst(const T&);
599
600
  template <class T>
601
  TypeNode mkTypeConst(const T&);
602
603
  template <class NodeClass, class T>
604
  NodeClass mkConstInternal(const T&);
605
606
  /** Create a node with children. */
607
  TypeNode mkTypeNode(Kind kind, TypeNode child1);
608
  TypeNode mkTypeNode(Kind kind, TypeNode child1, TypeNode child2);
609
  TypeNode mkTypeNode(Kind kind, TypeNode child1, TypeNode child2,
610
                      TypeNode child3);
611
  TypeNode mkTypeNode(Kind kind, const std::vector<TypeNode>& children);
612
613
  /**
614
   * Determine whether Nodes of a particular Kind have operators.
615
   * @returns true if Nodes of Kind k have operators.
616
   */
617
  static inline bool hasOperator(Kind k);
618
619
  /**
620
   * Get the (singleton) operator of an OPERATOR-kinded kind.  The
621
   * returned node n will have kind BUILTIN, and calling
622
   * n.getConst<cvc5::Kind>() will yield k.
623
   */
624
5392992
  inline TNode operatorOf(Kind k) {
625
5392992
    AssertArgument( kind::metaKindOf(k) == kind::metakind::OPERATOR, k,
626
                    "Kind is not an OPERATOR-kinded kind "
627
                    "in NodeManager::operatorOf()" );
628
5392992
    return d_operators[k];
629
  }
630
631
  /**
632
   * Retrieve an attribute for a node.
633
   *
634
   * @param nv the node value
635
   * @param attr an instance of the attribute kind to retrieve.
636
   * @returns the attribute, if set, or a default-constructed
637
   * <code>AttrKind::value_type</code> if not.
638
   */
639
  template <class AttrKind>
640
  inline typename AttrKind::value_type getAttribute(expr::NodeValue* nv,
641
                                                    const AttrKind& attr) const;
642
643
  /**
644
   * Check whether an attribute is set for a node.
645
   *
646
   * @param nv the node value
647
   * @param attr an instance of the attribute kind to check
648
   * @returns <code>true</code> iff <code>attr</code> is set for
649
   * <code>nv</code>.
650
   */
651
  template <class AttrKind>
652
  inline bool hasAttribute(expr::NodeValue* nv,
653
                           const AttrKind& attr) const;
654
655
  /**
656
   * Check whether an attribute is set for a node, and, if so,
657
   * retrieve it.
658
   *
659
   * @param nv the node value
660
   * @param attr an instance of the attribute kind to check
661
   * @param value a reference to an object of the attribute's value type.
662
   * <code>value</code> will be set to the value of the attribute, if it is
663
   * set for <code>nv</code>; otherwise, it will be set to the default
664
   * value of the attribute.
665
   * @returns <code>true</code> iff <code>attr</code> is set for
666
   * <code>nv</code>.
667
   */
668
  template <class AttrKind>
669
  inline bool getAttribute(expr::NodeValue* nv,
670
                           const AttrKind& attr,
671
                           typename AttrKind::value_type& value) const;
672
673
  /**
674
   * Set an attribute for a node.  If the node doesn't have the
675
   * attribute, this function assigns one.  If the node has one, this
676
   * overwrites it.
677
   *
678
   * @param nv the node value
679
   * @param attr an instance of the attribute kind to set
680
   * @param value the value of <code>attr</code> for <code>nv</code>
681
   */
682
  template <class AttrKind>
683
  inline void setAttribute(expr::NodeValue* nv,
684
                           const AttrKind& attr,
685
                           const typename AttrKind::value_type& value);
686
687
  /**
688
   * Retrieve an attribute for a TNode.
689
   *
690
   * @param n the node
691
   * @param attr an instance of the attribute kind to retrieve.
692
   * @returns the attribute, if set, or a default-constructed
693
   * <code>AttrKind::value_type</code> if not.
694
   */
695
  template <class AttrKind>
696
  inline typename AttrKind::value_type
697
  getAttribute(TNode n, const AttrKind& attr) const;
698
699
  /**
700
   * Check whether an attribute is set for a TNode.
701
   *
702
   * @param n the node
703
   * @param attr an instance of the attribute kind to check
704
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
705
   */
706
  template <class AttrKind>
707
  inline bool hasAttribute(TNode n,
708
                           const AttrKind& attr) const;
709
710
  /**
711
   * Check whether an attribute is set for a TNode and, if so, retieve
712
   * it.
713
   *
714
   * @param n the node
715
   * @param attr an instance of the attribute kind to check
716
   * @param value a reference to an object of the attribute's value type.
717
   * <code>value</code> will be set to the value of the attribute, if it is
718
   * set for <code>nv</code>; otherwise, it will be set to the default value of
719
   * the attribute.
720
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
721
   */
722
  template <class AttrKind>
723
  inline bool getAttribute(TNode n,
724
                           const AttrKind& attr,
725
                           typename AttrKind::value_type& value) const;
726
727
  /**
728
   * Set an attribute for a node.  If the node doesn't have the
729
   * attribute, this function assigns one.  If the node has one, this
730
   * overwrites it.
731
   *
732
   * @param n the node
733
   * @param attr an instance of the attribute kind to set
734
   * @param value the value of <code>attr</code> for <code>n</code>
735
   */
736
  template <class AttrKind>
737
  inline void setAttribute(TNode n,
738
                           const AttrKind& attr,
739
                           const typename AttrKind::value_type& value);
740
741
  /**
742
   * Retrieve an attribute for a TypeNode.
743
   *
744
   * @param n the type node
745
   * @param attr an instance of the attribute kind to retrieve.
746
   * @returns the attribute, if set, or a default-constructed
747
   * <code>AttrKind::value_type</code> if not.
748
   */
749
  template <class AttrKind>
750
  inline typename AttrKind::value_type
751
  getAttribute(TypeNode n, const AttrKind& attr) const;
752
753
  /**
754
   * Check whether an attribute is set for a TypeNode.
755
   *
756
   * @param n the type node
757
   * @param attr an instance of the attribute kind to check
758
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
759
   */
760
  template <class AttrKind>
761
  inline bool hasAttribute(TypeNode n,
762
                           const AttrKind& attr) const;
763
764
  /**
765
   * Check whether an attribute is set for a TypeNode and, if so, retieve
766
   * it.
767
   *
768
   * @param n the type node
769
   * @param attr an instance of the attribute kind to check
770
   * @param value a reference to an object of the attribute's value type.
771
   * <code>value</code> will be set to the value of the attribute, if it is
772
   * set for <code>nv</code>; otherwise, it will be set to the default value of
773
   * the attribute.
774
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
775
   */
776
  template <class AttrKind>
777
  inline bool getAttribute(TypeNode n,
778
                           const AttrKind& attr,
779
                           typename AttrKind::value_type& value) const;
780
781
  /**
782
   * Set an attribute for a type node.  If the node doesn't have the
783
   * attribute, this function assigns one.  If the type node has one,
784
   * this overwrites it.
785
   *
786
   * @param n the type node
787
   * @param attr an instance of the attribute kind to set
788
   * @param value the value of <code>attr</code> for <code>n</code>
789
   */
790
  template <class AttrKind>
791
  inline void setAttribute(TypeNode n,
792
                           const AttrKind& attr,
793
                           const typename AttrKind::value_type& value);
794
795
  /** Get the (singleton) type for Booleans. */
796
  TypeNode booleanType();
797
798
  /** Get the (singleton) type for integers. */
799
  TypeNode integerType();
800
801
  /** Get the (singleton) type for reals. */
802
  TypeNode realType();
803
804
  /** Get the (singleton) type for strings. */
805
  TypeNode stringType();
806
807
  /** Get the (singleton) type for RegExp. */
808
  TypeNode regExpType();
809
810
  /** Get the (singleton) type for rounding modes. */
811
  TypeNode roundingModeType();
812
813
  /** Get the bound var list type. */
814
  TypeNode boundVarListType();
815
816
  /** Get the instantiation pattern type. */
817
  TypeNode instPatternType();
818
819
  /** Get the instantiation pattern type. */
820
  TypeNode instPatternListType();
821
822
  /**
823
   * Get the (singleton) type for builtin operators (that is, the type
824
   * of the Node returned from Node::getOperator() when the operator
825
   * is built-in, like EQUAL). */
826
  TypeNode builtinOperatorType();
827
828
  /**
829
   * Make a function type from domain to range.
830
   *
831
   * @param domain the domain type
832
   * @param range the range type
833
   * @returns the functional type domain -> range
834
   */
835
  TypeNode mkFunctionType(const TypeNode& domain,
836
                          const TypeNode& range);
837
838
  /**
839
   * Make a function type with input types from
840
   * argTypes. <code>argTypes</code> must have at least one element.
841
   *
842
   * @param argTypes the domain is a tuple (argTypes[0], ..., argTypes[n])
843
   * @param range the range type
844
   * @returns the functional type (argTypes[0], ..., argTypes[n]) -> range
845
   */
846
  TypeNode mkFunctionType(const std::vector<TypeNode>& argTypes,
847
                          const TypeNode& range);
848
849
  /**
850
   * Make a function type with input types from
851
   * <code>sorts[0..sorts.size()-2]</code> and result type
852
   * <code>sorts[sorts.size()-1]</code>. <code>sorts</code> must have
853
   * at least 2 elements.
854
   *
855
   * @param sorts The argument and range sort of the function type, where the
856
   * range type is the last in this vector.
857
   * @return the function type
858
   */
859
  TypeNode mkFunctionType(const std::vector<TypeNode>& sorts);
860
861
  /**
862
   * Make a predicate type with input types from
863
   * <code>sorts</code>. The result with be a function type with range
864
   * <code>BOOLEAN</code>. <code>sorts</code> must have at least one
865
   * element.
866
   */
867
  TypeNode mkPredicateType(const std::vector<TypeNode>& sorts);
868
869
  /**
870
   * Make a tuple type with types from
871
   * <code>types</code>. <code>types</code> must have at least one
872
   * element.
873
   *
874
   * @param types a vector of types
875
   * @returns the tuple type (types[0], ..., types[n])
876
   */
877
  TypeNode mkTupleType(const std::vector<TypeNode>& types);
878
879
  /**
880
   * Make a record type with the description from rec.
881
   *
882
   * @param rec a description of the record
883
   * @returns the record type
884
   */
885
  TypeNode mkRecordType(const Record& rec);
886
887
  /**
888
   * @returns the symbolic expression type
889
   */
890
  TypeNode sExprType();
891
892
  /** Make the type of floating-point with <code>exp</code> bit exponent and
893
      <code>sig</code> bit significand */
894
  TypeNode mkFloatingPointType(unsigned exp, unsigned sig);
895
  TypeNode mkFloatingPointType(FloatingPointSize fs);
896
897
  /** Make the type of bitvectors of size <code>size</code> */
898
  TypeNode mkBitVectorType(unsigned size);
899
900
  /** Make the type of arrays with the given parameterization */
901
  inline TypeNode mkArrayType(TypeNode indexType, TypeNode constituentType);
902
903
  /** Make the type of set with the given parameterization */
904
  inline TypeNode mkSetType(TypeNode elementType);
905
906
  /** Make the type of bags with the given parameterization */
907
  TypeNode mkBagType(TypeNode elementType);
908
909
  /** Make the type of sequences with the given parameterization */
910
  TypeNode mkSequenceType(TypeNode elementType);
911
912
  /** Bits for use in mkDatatypeType() flags.
913
   *
914
   * DATATYPE_FLAG_PLACEHOLDER indicates that the type should not be printed
915
   * out as a definition, for example, in models or during dumping.
916
   */
917
  enum
918
  {
919
    DATATYPE_FLAG_NONE = 0,
920
    DATATYPE_FLAG_PLACEHOLDER = 1
921
  }; /* enum */
922
923
  /** Make a type representing the given datatype. */
924
  TypeNode mkDatatypeType(DType& datatype, uint32_t flags = DATATYPE_FLAG_NONE);
925
926
  /**
927
   * Make a set of types representing the given datatypes, which may be
928
   * mutually recursive.
929
   */
930
  std::vector<TypeNode> mkMutualDatatypeTypes(
931
      const std::vector<DType>& datatypes, uint32_t flags = DATATYPE_FLAG_NONE);
932
933
  /**
934
   * Make a set of types representing the given datatypes, which may
935
   * be mutually recursive.  unresolvedTypes is a set of SortTypes
936
   * that were used as placeholders in the Datatypes for the Datatypes
937
   * of the same name.  This is just a more complicated version of the
938
   * above mkMutualDatatypeTypes() function, but is required to handle
939
   * complex types.
940
   *
941
   * For example, unresolvedTypes might contain the single sort "list"
942
   * (with that name reported from SortType::getName()).  The
943
   * datatypes list might have the single datatype
944
   *
945
   *   DATATYPE
946
   *     list = cons(car:ARRAY INT OF list, cdr:list) | nil;
947
   *   END;
948
   *
949
   * To represent the Type of the array, the user had to create a
950
   * placeholder type (an uninterpreted sort) to stand for "list" in
951
   * the type of "car".  It is this placeholder sort that should be
952
   * passed in unresolvedTypes.  If the datatype was of the simpler
953
   * form:
954
   *
955
   *   DATATYPE
956
   *     list = cons(car:list, cdr:list) | nil;
957
   *   END;
958
   *
959
   * then no complicated Type needs to be created, and the above,
960
   * simpler form of mkMutualDatatypeTypes() is enough.
961
   */
962
  std::vector<TypeNode> mkMutualDatatypeTypes(
963
      const std::vector<DType>& datatypes,
964
      const std::set<TypeNode>& unresolvedTypes,
965
      uint32_t flags = DATATYPE_FLAG_NONE);
966
967
  /**
968
   * Make a type representing a constructor with the given argument (subfield)
969
   * types and return type range.
970
   */
971
  TypeNode mkConstructorType(const std::vector<TypeNode>& args, TypeNode range);
972
973
  /** Make a type representing a selector with the given parameterization */
974
  TypeNode mkSelectorType(TypeNode domain, TypeNode range);
975
976
  /** Make a type representing a tester with given parameterization */
977
  TypeNode mkTesterType(TypeNode domain);
978
979
  /** Make a type representing an updater with the given parameterization */
980
  TypeNode mkDatatypeUpdateType(TypeNode domain, TypeNode range);
981
982
  /** Bits for use in mkSort() flags. */
983
  enum
984
  {
985
    SORT_FLAG_NONE = 0,
986
    SORT_FLAG_PLACEHOLDER = 1
987
  }; /* enum */
988
989
  /** Make a new (anonymous) sort of arity 0. */
990
  TypeNode mkSort(uint32_t flags = SORT_FLAG_NONE);
991
992
  /** Make a new sort with the given name of arity 0. */
993
  TypeNode mkSort(const std::string& name, uint32_t flags = SORT_FLAG_NONE);
994
995
  /** Make a new sort by parameterizing the given sort constructor. */
996
  TypeNode mkSort(TypeNode constructor,
997
                  const std::vector<TypeNode>& children,
998
                  uint32_t flags = SORT_FLAG_NONE);
999
1000
  /** Make a new sort with the given name and arity. */
1001
  TypeNode mkSortConstructor(const std::string& name,
1002
                             size_t arity,
1003
                             uint32_t flags = SORT_FLAG_NONE);
1004
1005
  /**
1006
   * Get the type for the given node and optionally do type checking.
1007
   *
1008
   * Initial type computation will be near-constant time if
1009
   * type checking is not requested. Results are memoized, so that
1010
   * subsequent calls to getType() without type checking will be
1011
   * constant time.
1012
   *
1013
   * Initial type checking is linear in the size of the expression.
1014
   * Again, the results are memoized, so that subsequent calls to
1015
   * getType(), with or without type checking, will be constant
1016
   * time.
1017
   *
1018
   * NOTE: A TypeCheckingException can be thrown even when type
1019
   * checking is not requested. getType() will always return a
1020
   * valid and correct type and, thus, an exception will be thrown
1021
   * when no valid or correct type can be computed (e.g., if the
1022
   * arguments to a bit-vector operation aren't bit-vectors). When
1023
   * type checking is not requested, getType() will do the minimum
1024
   * amount of checking required to return a valid result.
1025
   *
1026
   * @param n the Node for which we want a type
1027
   * @param check whether we should check the type as we compute it
1028
   * (default: false)
1029
   */
1030
  TypeNode getType(TNode n, bool check = false);
1031
1032
  /** Reclaim zombies while there are more than k nodes in the pool (if possible).*/
1033
  void reclaimZombiesUntil(uint32_t k);
1034
1035
  /** Reclaims all zombies (if possible).*/
1036
  void reclaimAllZombies();
1037
1038
  /** Size of the node pool. */
1039
  size_t poolSize() const;
1040
1041
  /** Deletes a list of attributes from the NM's AttributeManager.*/
1042
  void deleteAttributes(const std::vector< const expr::attr::AttributeUniqueId* >& ids);
1043
1044
  /**
1045
   * This function gives developers a hook into the NodeManager.
1046
   * This can be changed in node_manager.cpp without recompiling most of cvc5.
1047
   *
1048
   * debugHook is a debugging only function, and should not be present in
1049
   * any published code!
1050
   */
1051
  void debugHook(int debugFlag);
1052
}; /* class NodeManager */
1053
1054
/**
1055
 * This class changes the "current" thread-global
1056
 * <code>NodeManager</code> when it is created and reinstates the
1057
 * previous thread-global <code>NodeManager</code> when it is
1058
 * destroyed, effectively maintaining a set of nested
1059
 * <code>NodeManager</code> scopes.  This is especially useful on
1060
 * public-interface calls into the cvc5 library, where cvc5's notion
1061
 * of the "current" <code>NodeManager</code> should be set to match
1062
 * the calling context.  See, for example, the implementations of
1063
 * public calls in the <code>SmtEngine</code> class.
1064
 *
1065
 * The client must be careful to create and destroy
1066
 * <code>NodeManagerScope</code> objects in a well-nested manner (such
1067
 * as on the stack). You may create a <code>NodeManagerScope</code>
1068
 * with <code>new</code> and destroy it with <code>delete</code>, or
1069
 * place it as a data member of an object that is, but if the scope of
1070
 * these <code>new</code>/<code>delete</code> pairs isn't properly
1071
 * maintained, the incorrect "current" <code>NodeManager</code>
1072
 * pointer may be restored after a delete.
1073
 */
1074
class NodeManagerScope {
1075
  /** The old NodeManager, to be restored on destruction. */
1076
  NodeManager* d_oldNodeManager;
1077
public:
1078
990869911
 NodeManagerScope(NodeManager* nm) : d_oldNodeManager(NodeManager::s_current)
1079
 {
1080
990869911
   NodeManager::s_current = nm;
1081
990869911
   Debug("current") << "node manager scope: " << NodeManager::s_current << "\n";
1082
990869911
  }
1083
1084
1981739822
  ~NodeManagerScope() {
1085
990869911
    NodeManager::s_current = d_oldNodeManager;
1086
1981739822
    Debug("current") << "node manager scope: "
1087
990869911
                     << "returning to " << NodeManager::s_current << "\n";
1088
990869911
  }
1089
};/* class NodeManagerScope */
1090
1091
10462
inline TypeNode NodeManager::mkArrayType(TypeNode indexType,
1092
                                         TypeNode constituentType) {
1093
10462
  CheckArgument(!indexType.isNull(), indexType,
1094
                "unexpected NULL index type");
1095
10462
  CheckArgument(!constituentType.isNull(), constituentType,
1096
                "unexpected NULL constituent type");
1097
10462
  CheckArgument(indexType.isFirstClass(),
1098
                indexType,
1099
                "cannot index arrays by types that are not first-class. Try "
1100
                "option --uf-ho.");
1101
10462
  CheckArgument(constituentType.isFirstClass(),
1102
                constituentType,
1103
                "cannot store types that are not first-class in arrays. Try "
1104
                "option --uf-ho.");
1105
20924
  Debug("arrays") << "making array type " << indexType << " "
1106
10462
                  << constituentType << std::endl;
1107
10462
  return mkTypeNode(kind::ARRAY_TYPE, indexType, constituentType);
1108
}
1109
1110
12976
inline TypeNode NodeManager::mkSetType(TypeNode elementType) {
1111
12976
  CheckArgument(!elementType.isNull(), elementType,
1112
                "unexpected NULL element type");
1113
12976
  CheckArgument(elementType.isFirstClass(),
1114
                elementType,
1115
                "cannot store types that are not first-class in sets. Try "
1116
                "option --uf-ho.");
1117
12976
  Debug("sets") << "making sets type " << elementType << std::endl;
1118
12976
  return mkTypeNode(kind::SET_TYPE, elementType);
1119
}
1120
1121
444400795
inline expr::NodeValue* NodeManager::poolLookup(expr::NodeValue* nv) const {
1122
444400795
  NodeValuePool::const_iterator find = d_nodeValuePool.find(nv);
1123
444400795
  if(find == d_nodeValuePool.end()) {
1124
28400868
    return NULL;
1125
  } else {
1126
415999927
    return *find;
1127
  }
1128
}
1129
1130
28408540
inline void NodeManager::poolInsert(expr::NodeValue* nv) {
1131
28408540
  Assert(d_nodeValuePool.find(nv) == d_nodeValuePool.end())
1132
      << "NodeValue already in the pool!";
1133
28408540
  d_nodeValuePool.insert(nv);// FIXME multithreading
1134
28408540
}
1135
1136
28408540
inline void NodeManager::poolRemove(expr::NodeValue* nv) {
1137
28408540
  Assert(d_nodeValuePool.find(nv) != d_nodeValuePool.end())
1138
      << "NodeValue is not in the pool!";
1139
1140
28408540
  d_nodeValuePool.erase(nv);// FIXME multithreading
1141
28408540
}
1142
1143
}  // namespace cvc5
1144
1145
#define CVC5__NODE_MANAGER_NEEDS_CONSTANT_MAP
1146
#include "expr/metakind.h"
1147
#undef CVC5__NODE_MANAGER_NEEDS_CONSTANT_MAP
1148
1149
#include "expr/node_builder.h"
1150
1151
namespace cvc5 {
1152
1153
// general expression-builders
1154
1155
17257846
inline bool NodeManager::hasOperator(Kind k) {
1156
17257846
  switch(kind::MetaKind mk = kind::metaKindOf(k)) {
1157
1158
1946094
  case kind::metakind::INVALID:
1159
  case kind::metakind::VARIABLE:
1160
  case kind::metakind::NULLARY_OPERATOR:
1161
1946094
    return false;
1162
1163
13530267
  case kind::metakind::OPERATOR:
1164
  case kind::metakind::PARAMETERIZED:
1165
13530267
    return true;
1166
1167
1781485
  case kind::metakind::CONSTANT:
1168
1781485
    return false;
1169
1170
  default: Unhandled() << mk;
1171
  }
1172
}
1173
1174
586094
inline Kind NodeManager::operatorToKind(TNode n) {
1175
586094
  return kind::operatorToKind(n.d_nv);
1176
}
1177
1178
9580
inline Node NodeManager::mkNode(Kind kind)
1179
{
1180
19160
  NodeBuilder nb(this, kind);
1181
19160
  return nb.constructNode();
1182
}
1183
1184
50699282
inline Node NodeManager::mkNode(Kind kind, TNode child1) {
1185
101398564
  NodeBuilder nb(this, kind);
1186
50699282
  nb << child1;
1187
101398552
  return nb.constructNode();
1188
}
1189
1190
111165573
inline Node NodeManager::mkNode(Kind kind, TNode child1, TNode child2) {
1191
222331146
  NodeBuilder nb(this, kind);
1192
111165573
  nb << child1 << child2;
1193
222330772
  return nb.constructNode();
1194
}
1195
1196
834698
inline Node NodeManager::mkNode(Kind kind, TNode child1, TNode child2,
1197
                                TNode child3) {
1198
1669396
  NodeBuilder nb(this, kind);
1199
834698
  nb << child1 << child2 << child3;
1200
1669364
  return nb.constructNode();
1201
}
1202
1203
// N-ary version
1204
template <bool ref_count>
1205
14971378
inline Node NodeManager::mkNode(Kind kind,
1206
                                const std::vector<NodeTemplate<ref_count> >&
1207
                                children) {
1208
29942756
  NodeBuilder nb(this, kind);
1209
14971378
  nb.append(children);
1210
29942727
  return nb.constructNode();
1211
}
1212
1213
template <bool ref_count>
1214
714919
Node NodeManager::mkAnd(const std::vector<NodeTemplate<ref_count> >& children)
1215
{
1216
714919
  if (children.empty())
1217
  {
1218
38344
    return mkConst(true);
1219
  }
1220
676575
  else if (children.size() == 1)
1221
  {
1222
409463
    return children[0];
1223
  }
1224
267112
  return mkNode(kind::AND, children);
1225
}
1226
1227
template <bool ref_count>
1228
747727
Node NodeManager::mkOr(const std::vector<NodeTemplate<ref_count> >& children)
1229
{
1230
747727
  if (children.empty())
1231
  {
1232
1894
    return mkConst(false);
1233
  }
1234
745833
  else if (children.size() == 1)
1235
  {
1236
30586
    return children[0];
1237
  }
1238
715247
  return mkNode(kind::OR, children);
1239
}
1240
1241
// for operators
1242
inline Node NodeManager::mkNode(TNode opNode) {
1243
  NodeBuilder nb(this, operatorToKind(opNode));
1244
  if(opNode.getKind() != kind::BUILTIN) {
1245
    nb << opNode;
1246
  }
1247
  return nb.constructNode();
1248
}
1249
1250
267313
inline Node NodeManager::mkNode(TNode opNode, TNode child1) {
1251
534626
  NodeBuilder nb(this, operatorToKind(opNode));
1252
267313
  if(opNode.getKind() != kind::BUILTIN) {
1253
267313
    nb << opNode;
1254
  }
1255
267313
  nb << child1;
1256
534626
  return nb.constructNode();
1257
}
1258
1259
64
inline Node NodeManager::mkNode(TNode opNode, TNode child1, TNode child2) {
1260
128
  NodeBuilder nb(this, operatorToKind(opNode));
1261
64
  if(opNode.getKind() != kind::BUILTIN) {
1262
64
    nb << opNode;
1263
  }
1264
64
  nb << child1 << child2;
1265
128
  return nb.constructNode();
1266
}
1267
1268
inline Node NodeManager::mkNode(TNode opNode, TNode child1, TNode child2,
1269
                                TNode child3) {
1270
  NodeBuilder nb(this, operatorToKind(opNode));
1271
  if(opNode.getKind() != kind::BUILTIN) {
1272
    nb << opNode;
1273
  }
1274
  nb << child1 << child2 << child3;
1275
  return nb.constructNode();
1276
}
1277
1278
// N-ary version for operators
1279
template <bool ref_count>
1280
46515
inline Node NodeManager::mkNode(TNode opNode,
1281
                                const std::vector<NodeTemplate<ref_count> >&
1282
                                children) {
1283
93030
  NodeBuilder nb(this, operatorToKind(opNode));
1284
46515
  if(opNode.getKind() != kind::BUILTIN) {
1285
866
    nb << opNode;
1286
  }
1287
46515
  nb.append(children);
1288
93030
  return nb.constructNode();
1289
}
1290
1291
28952
inline TypeNode NodeManager::mkTypeNode(Kind kind, TypeNode child1) {
1292
28952
  return (NodeBuilder(this, kind) << child1).constructTypeNode();
1293
}
1294
1295
42647
inline TypeNode NodeManager::mkTypeNode(Kind kind, TypeNode child1,
1296
                                        TypeNode child2) {
1297
42647
  return (NodeBuilder(this, kind) << child1 << child2).constructTypeNode();
1298
}
1299
1300
inline TypeNode NodeManager::mkTypeNode(Kind kind, TypeNode child1,
1301
                                        TypeNode child2, TypeNode child3) {
1302
  return (NodeBuilder(this, kind) << child1 << child2 << child3)
1303
      .constructTypeNode();
1304
}
1305
1306
// N-ary version for types
1307
73513
inline TypeNode NodeManager::mkTypeNode(Kind kind,
1308
                                        const std::vector<TypeNode>& children) {
1309
73513
  return NodeBuilder(this, kind).append(children).constructTypeNode();
1310
}
1311
1312
template <class T>
1313
194595137
Node NodeManager::mkConst(const T& val) {
1314
194595137
  return mkConstInternal<Node, T>(val);
1315
}
1316
1317
template <class T>
1318
29755045
TypeNode NodeManager::mkTypeConst(const T& val) {
1319
29755045
  return mkConstInternal<TypeNode, T>(val);
1320
}
1321
1322
template <class NodeClass, class T>
1323
224350182
NodeClass NodeManager::mkConstInternal(const T& val) {
1324
  // This method indirectly calls `NodeValue::inc()`, which relies on having
1325
  // the correct `NodeManager` in scope.
1326
448700364
  NodeManagerScope nms(this);
1327
1328
  // typedef typename kind::metakind::constantMap<T>::OwningTheory theory_t;
1329
224350182
  NVStorage<1> nvStorage;
1330
224350182
  expr::NodeValue& nvStack = reinterpret_cast<expr::NodeValue&>(nvStorage);
1331
1332
224350182
  nvStack.d_id = 0;
1333
224350182
  nvStack.d_kind = kind::metakind::ConstantMap<T>::kind;
1334
224350182
  nvStack.d_rc = 0;
1335
224350182
  nvStack.d_nchildren = 1;
1336
1337
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1338
#pragma GCC diagnostic push
1339
#pragma GCC diagnostic ignored "-Warray-bounds"
1340
#endif
1341
1342
224350182
  nvStack.d_children[0] =
1343
    const_cast<expr::NodeValue*>(reinterpret_cast<const expr::NodeValue*>(&val));
1344
224350182
  expr::NodeValue* nv = poolLookup(&nvStack);
1345
1346
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1347
#pragma GCC diagnostic pop
1348
#endif
1349
1350
224350182
  if(nv != NULL) {
1351
221727914
    return NodeClass(nv);
1352
  }
1353
1354
2622268
  nv = (expr::NodeValue*)
1355
2622268
    std::malloc(sizeof(expr::NodeValue) + sizeof(T));
1356
2622268
  if(nv == NULL) {
1357
    throw std::bad_alloc();
1358
  }
1359
1360
2622268
  nv->d_nchildren = 0;
1361
2622268
  nv->d_kind = kind::metakind::ConstantMap<T>::kind;
1362
2622268
  nv->d_id = next_id++;// FIXME multithreading
1363
2622268
  nv->d_rc = 0;
1364
1365
  //OwningTheory::mkConst(val);
1366
2622268
  new (&nv->d_children) T(val);
1367
1368
2622268
  poolInsert(nv);
1369
2622268
  if(Debug.isOn("gc")) {
1370
    Debug("gc") << "creating node value " << nv
1371
                << " [" << nv->d_id << "]: ";
1372
    nv->printAst(Debug("gc"));
1373
    Debug("gc") << std::endl;
1374
  }
1375
1376
2622268
  return NodeClass(nv);
1377
}
1378
1379
}  // namespace cvc5
1380
1381
#endif /* CVC5__NODE_MANAGER_H */