GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node_manager.h Lines: 170 201 84.6 %
Date: 2021-05-21 Branches: 541 2054 26.3 %

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
18541
class NodeManagerListener {
63
 public:
64
18541
  virtual ~NodeManagerListener() {}
65
2826
  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
1222
  virtual void nmNotifyNewDatatypes(const std::vector<TypeNode>& datatypes,
70
                                    uint32_t flags)
71
  {
72
1222
  }
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
8171866
  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
29140686
    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
16756
  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
15264
  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
15462166350
  inline bool isCurrentlyDeleting(const expr::NodeValue* nv) const {
261
15462166350
    return d_nodeUnderDeletion == nv;
262
  }
263
264
  /**
265
   * Register a NodeValue as a zombie.
266
   */
267
45516116
  inline void markForDeletion(expr::NodeValue* nv) {
268
45516116
    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
45516116
    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
45516116
    Assert(d_zombies.find(nv) == d_zombies.end() || *d_zombies.find(nv) == nv);
285
286
45516116
    d_zombies.insert(nv);
287
288
45516116
    if(safeToReclaimZombies()) {
289
30622611
      if(d_zombies.size() > 5000) {
290
2502
        reclaimZombies();
291
      }
292
    }
293
45516116
  }
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
218512464
  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
71271209994
  static NodeManager* currentNM() { return s_current; }
381
  /** Get this node manager's skolem manager */
382
209079
  SkolemManager* getSkolemManager() { return d_skManager.get(); }
383
  /** Get this node manager's bound variable manager */
384
694976
  BoundVarManager* getBoundVarManager() { return d_bvManager.get(); }
385
386
  /** Subscribe to NodeManager events */
387
16929
  void subscribeEvents(NodeManagerListener* listener) {
388
16929
    Assert(std::find(d_listeners.begin(), d_listeners.end(), listener)
389
           == d_listeners.end())
390
        << "listener already subscribed";
391
16929
    d_listeners.push_back(listener);
392
16929
  }
393
394
  /** Unsubscribe from NodeManager events */
395
16929
  void unsubscribeEvents(NodeManagerListener* listener) {
396
16929
    std::vector<NodeManagerListener*>::iterator elt = std::find(d_listeners.begin(), d_listeners.end(), listener);
397
16929
    Assert(elt != d_listeners.end()) << "listener not subscribed";
398
16929
    d_listeners.erase(elt);
399
16929
  }
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 one child. */
433
  Node mkNode(Kind kind, TNode child1);
434
435
  /** Create a node with two children. */
436
  Node mkNode(Kind kind, TNode child1, TNode child2);
437
438
  /** Create a node with three children. */
439
  Node mkNode(Kind kind, TNode child1, TNode child2, TNode child3);
440
441
  /** Create a node with four children. */
442
  Node mkNode(Kind kind, TNode child1, TNode child2, TNode child3,
443
              TNode child4);
444
445
  /** Create a node with five children. */
446
  Node mkNode(Kind kind, TNode child1, TNode child2, TNode child3,
447
              TNode child4, TNode child5);
448
449
  /** Create a node with an arbitrary number of children. */
450
  template <bool ref_count>
451
  Node mkNode(Kind kind, const std::vector<NodeTemplate<ref_count> >& children);
452
453
  /**
454
   * Create an AND node with arbitrary number of children. This returns the
455
   * true node if children is empty, or the single node in children if
456
   * it contains only one node.
457
   *
458
   * We define construction of AND as a special case here since it is widely
459
   * used for e.g. constructing explanations.
460
   */
461
  template <bool ref_count>
462
  Node mkAnd(const std::vector<NodeTemplate<ref_count> >& children);
463
464
  /**
465
   * Create an OR node with arbitrary number of children. This returns the
466
   * false node if children is empty, or the single node in children if
467
   * it contains only one node.
468
   *
469
   * We define construction of OR as a special case here since it is widely
470
   * used for e.g. constructing explanations or lemmas.
471
   */
472
  template <bool ref_count>
473
  Node mkOr(const std::vector<NodeTemplate<ref_count> >& children);
474
475
  /** Create a node (with no children) by operator. */
476
  Node mkNode(TNode opNode);
477
478
  /** Create a node with one child by operator. */
479
  Node mkNode(TNode opNode, TNode child1);
480
481
  /** Create a node with two children by operator. */
482
  Node mkNode(TNode opNode, TNode child1, TNode child2);
483
484
  /** Create a node with three children by operator. */
485
  Node mkNode(TNode opNode, TNode child1, TNode child2, TNode child3);
486
487
  /** Create a node with four children by operator. */
488
  Node mkNode(TNode opNode, TNode child1, TNode child2, TNode child3,
489
              TNode child4);
490
491
  /** Create a node with five children by operator. */
492
  Node mkNode(TNode opNode, TNode child1, TNode child2, TNode child3,
493
              TNode child4, TNode child5);
494
495
  /** Create a node by applying an operator to the children. */
496
  template <bool ref_count>
497
  Node mkNode(TNode opNode, const std::vector<NodeTemplate<ref_count> >& children);
498
499
  Node mkBoundVar(const std::string& name, const TypeNode& type);
500
501
  Node mkBoundVar(const TypeNode& type);
502
503
  /** get the canonical bound variable list for function type tn */
504
  Node getBoundVarListForFunctionType( TypeNode tn );
505
506
  /**
507
   * Create an Node by applying an associative operator to the children.
508
   * If <code>children.size()</code> is greater than the max arity for
509
   * <code>kind</code>, then the expression will be broken up into
510
   * suitably-sized chunks, taking advantage of the associativity of
511
   * <code>kind</code>. For example, if kind <code>FOO</code> has max arity
512
   * 2, then calling <code>mkAssociative(FOO,a,b,c)</code> will return
513
   * <code>(FOO (FOO a b) c)</code> or <code>(FOO a (FOO b c))</code>.
514
   * The order of the arguments will be preserved in a left-to-right
515
   * traversal of the resulting tree.
516
   */
517
  Node mkAssociative(Kind kind, const std::vector<Node>& children);
518
519
  /**
520
   * Create an Node by applying an binary left-associative operator to the
521
   * children. For example, mkLeftAssociative( f, { a, b, c } ) returns
522
   * f( f( a, b ), c ).
523
   */
524
  Node mkLeftAssociative(Kind kind, const std::vector<Node>& children);
525
  /**
526
   * Create an Node by applying an binary right-associative operator to the
527
   * children. For example, mkRightAssociative( f, { a, b, c } ) returns
528
   * f( a, f( b, c ) ).
529
   */
530
  Node mkRightAssociative(Kind kind, const std::vector<Node>& children);
531
532
  /** make chain
533
   *
534
   * Given a kind k and arguments t_1, ..., t_n, this returns the
535
   * conjunction of:
536
   *  (k t_1 t_2) .... (k t_{n-1} t_n)
537
   * It is expected that k is a kind denoting a predicate, and args is a list
538
   * of terms of size >= 2 such that the terms above are well-typed.
539
   */
540
  Node mkChain(Kind kind, const std::vector<Node>& children);
541
542
  /**
543
   * Optional flags used to control behavior of NodeManager::mkSkolem().
544
   * They should be composed with a bitwise OR (e.g.,
545
   * "SKOLEM_NO_NOTIFY | SKOLEM_EXACT_NAME").  Of course, SKOLEM_DEFAULT
546
   * cannot be composed in such a manner.
547
   */
548
  enum SkolemFlags
549
  {
550
    SKOLEM_DEFAULT = 0,    /**< default behavior */
551
    SKOLEM_NO_NOTIFY = 1,  /**< do not notify subscribers */
552
    SKOLEM_EXACT_NAME = 2, /**< do not make the name unique by adding the id */
553
    SKOLEM_IS_GLOBAL = 4,  /**< global vars appear in models even after a pop */
554
    SKOLEM_BOOL_TERM_VAR = 8 /**< vars requiring kind BOOLEAN_TERM_VARIABLE */
555
  };                         /* enum SkolemFlags */
556
557
  /** Create a instantiation constant with the given type. */
558
  Node mkInstConstant(const TypeNode& type);
559
560
  /** Create a boolean term variable. */
561
  Node mkBooleanTermVariable();
562
563
  /** Make a new abstract value with the given type. */
564
  Node mkAbstractValue(const TypeNode& type);
565
566
  /** make unique (per Type,Kind) variable. */
567
  Node mkNullaryOperator(const TypeNode& type, Kind k);
568
569
  /**
570
  * Create a singleton set from the given element n.
571
  * @param t the element type of the returned set.
572
  *          Note that the type of n needs to be a subtype of t.
573
  * @param n the single element in the singleton.
574
  * @return a singleton set constructed from the element n.
575
  */
576
  Node mkSingleton(const TypeNode& t, const TNode n);
577
578
  /**
579
  * Create a bag from the given element n along with its multiplicity m.
580
  * @param t the element type of the returned bag.
581
  *          Note that the type of n needs to be a subtype of t.
582
  * @param n the element that is used to to construct the bag
583
  * @param m the multiplicity of the element n
584
  * @return a bag that contains m occurrences of n.
585
  */
586
  Node mkBag(const TypeNode& t, const TNode n, const TNode m);
587
588
  /**
589
   * Create a constant of type T.  It will have the appropriate
590
   * CONST_* kind defined for T.
591
   */
592
  template <class T>
593
  Node mkConst(const T&);
594
595
  template <class T>
596
  TypeNode mkTypeConst(const T&);
597
598
  template <class NodeClass, class T>
599
  NodeClass mkConstInternal(const T&);
600
601
  /** Create a node with children. */
602
  TypeNode mkTypeNode(Kind kind, TypeNode child1);
603
  TypeNode mkTypeNode(Kind kind, TypeNode child1, TypeNode child2);
604
  TypeNode mkTypeNode(Kind kind, TypeNode child1, TypeNode child2,
605
                      TypeNode child3);
606
  TypeNode mkTypeNode(Kind kind, const std::vector<TypeNode>& children);
607
608
  /**
609
   * Determine whether Nodes of a particular Kind have operators.
610
   * @returns true if Nodes of Kind k have operators.
611
   */
612
  static inline bool hasOperator(Kind k);
613
614
  /**
615
   * Get the (singleton) operator of an OPERATOR-kinded kind.  The
616
   * returned node n will have kind BUILTIN, and calling
617
   * n.getConst<cvc5::Kind>() will yield k.
618
   */
619
5294819
  inline TNode operatorOf(Kind k) {
620
5294819
    AssertArgument( kind::metaKindOf(k) == kind::metakind::OPERATOR, k,
621
                    "Kind is not an OPERATOR-kinded kind "
622
                    "in NodeManager::operatorOf()" );
623
5294819
    return d_operators[k];
624
  }
625
626
  /**
627
   * Retrieve an attribute for a node.
628
   *
629
   * @param nv the node value
630
   * @param attr an instance of the attribute kind to retrieve.
631
   * @returns the attribute, if set, or a default-constructed
632
   * <code>AttrKind::value_type</code> if not.
633
   */
634
  template <class AttrKind>
635
  inline typename AttrKind::value_type getAttribute(expr::NodeValue* nv,
636
                                                    const AttrKind& attr) const;
637
638
  /**
639
   * Check whether an attribute is set for a node.
640
   *
641
   * @param nv the node value
642
   * @param attr an instance of the attribute kind to check
643
   * @returns <code>true</code> iff <code>attr</code> is set for
644
   * <code>nv</code>.
645
   */
646
  template <class AttrKind>
647
  inline bool hasAttribute(expr::NodeValue* nv,
648
                           const AttrKind& attr) const;
649
650
  /**
651
   * Check whether an attribute is set for a node, and, if so,
652
   * retrieve it.
653
   *
654
   * @param nv the node value
655
   * @param attr an instance of the attribute kind to check
656
   * @param value a reference to an object of the attribute's value type.
657
   * <code>value</code> will be set to the value of the attribute, if it is
658
   * set for <code>nv</code>; otherwise, it will be set to the default
659
   * value of the attribute.
660
   * @returns <code>true</code> iff <code>attr</code> is set for
661
   * <code>nv</code>.
662
   */
663
  template <class AttrKind>
664
  inline bool getAttribute(expr::NodeValue* nv,
665
                           const AttrKind& attr,
666
                           typename AttrKind::value_type& value) const;
667
668
  /**
669
   * Set an attribute for a node.  If the node doesn't have the
670
   * attribute, this function assigns one.  If the node has one, this
671
   * overwrites it.
672
   *
673
   * @param nv the node value
674
   * @param attr an instance of the attribute kind to set
675
   * @param value the value of <code>attr</code> for <code>nv</code>
676
   */
677
  template <class AttrKind>
678
  inline void setAttribute(expr::NodeValue* nv,
679
                           const AttrKind& attr,
680
                           const typename AttrKind::value_type& value);
681
682
  /**
683
   * Retrieve an attribute for a TNode.
684
   *
685
   * @param n the node
686
   * @param attr an instance of the attribute kind to retrieve.
687
   * @returns the attribute, if set, or a default-constructed
688
   * <code>AttrKind::value_type</code> if not.
689
   */
690
  template <class AttrKind>
691
  inline typename AttrKind::value_type
692
  getAttribute(TNode n, const AttrKind& attr) const;
693
694
  /**
695
   * Check whether an attribute is set for a TNode.
696
   *
697
   * @param n the node
698
   * @param attr an instance of the attribute kind to check
699
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
700
   */
701
  template <class AttrKind>
702
  inline bool hasAttribute(TNode n,
703
                           const AttrKind& attr) const;
704
705
  /**
706
   * Check whether an attribute is set for a TNode and, if so, retieve
707
   * it.
708
   *
709
   * @param n the node
710
   * @param attr an instance of the attribute kind to check
711
   * @param value a reference to an object of the attribute's value type.
712
   * <code>value</code> will be set to the value of the attribute, if it is
713
   * set for <code>nv</code>; otherwise, it will be set to the default value of
714
   * the attribute.
715
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
716
   */
717
  template <class AttrKind>
718
  inline bool getAttribute(TNode n,
719
                           const AttrKind& attr,
720
                           typename AttrKind::value_type& value) const;
721
722
  /**
723
   * Set an attribute for a node.  If the node doesn't have the
724
   * attribute, this function assigns one.  If the node has one, this
725
   * overwrites it.
726
   *
727
   * @param n the node
728
   * @param attr an instance of the attribute kind to set
729
   * @param value the value of <code>attr</code> for <code>n</code>
730
   */
731
  template <class AttrKind>
732
  inline void setAttribute(TNode n,
733
                           const AttrKind& attr,
734
                           const typename AttrKind::value_type& value);
735
736
  /**
737
   * Retrieve an attribute for a TypeNode.
738
   *
739
   * @param n the type node
740
   * @param attr an instance of the attribute kind to retrieve.
741
   * @returns the attribute, if set, or a default-constructed
742
   * <code>AttrKind::value_type</code> if not.
743
   */
744
  template <class AttrKind>
745
  inline typename AttrKind::value_type
746
  getAttribute(TypeNode n, const AttrKind& attr) const;
747
748
  /**
749
   * Check whether an attribute is set for a TypeNode.
750
   *
751
   * @param n the type node
752
   * @param attr an instance of the attribute kind to check
753
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
754
   */
755
  template <class AttrKind>
756
  inline bool hasAttribute(TypeNode n,
757
                           const AttrKind& attr) const;
758
759
  /**
760
   * Check whether an attribute is set for a TypeNode and, if so, retieve
761
   * it.
762
   *
763
   * @param n the type node
764
   * @param attr an instance of the attribute kind to check
765
   * @param value a reference to an object of the attribute's value type.
766
   * <code>value</code> will be set to the value of the attribute, if it is
767
   * set for <code>nv</code>; otherwise, it will be set to the default value of
768
   * the attribute.
769
   * @returns <code>true</code> iff <code>attr</code> is set for <code>n</code>.
770
   */
771
  template <class AttrKind>
772
  inline bool getAttribute(TypeNode n,
773
                           const AttrKind& attr,
774
                           typename AttrKind::value_type& value) const;
775
776
  /**
777
   * Set an attribute for a type node.  If the node doesn't have the
778
   * attribute, this function assigns one.  If the type node has one,
779
   * this overwrites it.
780
   *
781
   * @param n the type node
782
   * @param attr an instance of the attribute kind to set
783
   * @param value the value of <code>attr</code> for <code>n</code>
784
   */
785
  template <class AttrKind>
786
  inline void setAttribute(TypeNode n,
787
                           const AttrKind& attr,
788
                           const typename AttrKind::value_type& value);
789
790
  /** Get the (singleton) type for Booleans. */
791
  TypeNode booleanType();
792
793
  /** Get the (singleton) type for integers. */
794
  TypeNode integerType();
795
796
  /** Get the (singleton) type for reals. */
797
  TypeNode realType();
798
799
  /** Get the (singleton) type for strings. */
800
  TypeNode stringType();
801
802
  /** Get the (singleton) type for RegExp. */
803
  TypeNode regExpType();
804
805
  /** Get the (singleton) type for rounding modes. */
806
  TypeNode roundingModeType();
807
808
  /** Get the bound var list type. */
809
  TypeNode boundVarListType();
810
811
  /** Get the instantiation pattern type. */
812
  TypeNode instPatternType();
813
814
  /** Get the instantiation pattern type. */
815
  TypeNode instPatternListType();
816
817
  /**
818
   * Get the (singleton) type for builtin operators (that is, the type
819
   * of the Node returned from Node::getOperator() when the operator
820
   * is built-in, like EQUAL). */
821
  TypeNode builtinOperatorType();
822
823
  /**
824
   * Make a function type from domain to range.
825
   *
826
   * @param domain the domain type
827
   * @param range the range type
828
   * @returns the functional type domain -> range
829
   */
830
  TypeNode mkFunctionType(const TypeNode& domain,
831
                          const TypeNode& range);
832
833
  /**
834
   * Make a function type with input types from
835
   * argTypes. <code>argTypes</code> must have at least one element.
836
   *
837
   * @param argTypes the domain is a tuple (argTypes[0], ..., argTypes[n])
838
   * @param range the range type
839
   * @returns the functional type (argTypes[0], ..., argTypes[n]) -> range
840
   */
841
  TypeNode mkFunctionType(const std::vector<TypeNode>& argTypes,
842
                          const TypeNode& range);
843
844
  /**
845
   * Make a function type with input types from
846
   * <code>sorts[0..sorts.size()-2]</code> and result type
847
   * <code>sorts[sorts.size()-1]</code>. <code>sorts</code> must have
848
   * at least 2 elements.
849
   *
850
   * @param sorts The argument and range sort of the function type, where the
851
   * range type is the last in this vector.
852
   * @return the function type
853
   */
854
  TypeNode mkFunctionType(const std::vector<TypeNode>& sorts);
855
856
  /**
857
   * Make a predicate type with input types from
858
   * <code>sorts</code>. The result with be a function type with range
859
   * <code>BOOLEAN</code>. <code>sorts</code> must have at least one
860
   * element.
861
   */
862
  TypeNode mkPredicateType(const std::vector<TypeNode>& sorts);
863
864
  /**
865
   * Make a tuple type with types from
866
   * <code>types</code>. <code>types</code> must have at least one
867
   * element.
868
   *
869
   * @param types a vector of types
870
   * @returns the tuple type (types[0], ..., types[n])
871
   */
872
  TypeNode mkTupleType(const std::vector<TypeNode>& types);
873
874
  /**
875
   * Make a record type with the description from rec.
876
   *
877
   * @param rec a description of the record
878
   * @returns the record type
879
   */
880
  TypeNode mkRecordType(const Record& rec);
881
882
  /**
883
   * @returns the symbolic expression type
884
   */
885
  TypeNode sExprType();
886
887
  /** Make the type of floating-point with <code>exp</code> bit exponent and
888
      <code>sig</code> bit significand */
889
  TypeNode mkFloatingPointType(unsigned exp, unsigned sig);
890
  TypeNode mkFloatingPointType(FloatingPointSize fs);
891
892
  /** Make the type of bitvectors of size <code>size</code> */
893
  TypeNode mkBitVectorType(unsigned size);
894
895
  /** Make the type of arrays with the given parameterization */
896
  inline TypeNode mkArrayType(TypeNode indexType, TypeNode constituentType);
897
898
  /** Make the type of set with the given parameterization */
899
  inline TypeNode mkSetType(TypeNode elementType);
900
901
  /** Make the type of bags with the given parameterization */
902
  TypeNode mkBagType(TypeNode elementType);
903
904
  /** Make the type of sequences with the given parameterization */
905
  TypeNode mkSequenceType(TypeNode elementType);
906
907
  /** Bits for use in mkDatatypeType() flags.
908
   *
909
   * DATATYPE_FLAG_PLACEHOLDER indicates that the type should not be printed
910
   * out as a definition, for example, in models or during dumping.
911
   */
912
  enum
913
  {
914
    DATATYPE_FLAG_NONE = 0,
915
    DATATYPE_FLAG_PLACEHOLDER = 1
916
  }; /* enum */
917
918
  /** Make a type representing the given datatype. */
919
  TypeNode mkDatatypeType(DType& datatype, uint32_t flags = DATATYPE_FLAG_NONE);
920
921
  /**
922
   * Make a set of types representing the given datatypes, which may be
923
   * mutually recursive.
924
   */
925
  std::vector<TypeNode> mkMutualDatatypeTypes(
926
      const std::vector<DType>& datatypes, uint32_t flags = DATATYPE_FLAG_NONE);
927
928
  /**
929
   * Make a set of types representing the given datatypes, which may
930
   * be mutually recursive.  unresolvedTypes is a set of SortTypes
931
   * that were used as placeholders in the Datatypes for the Datatypes
932
   * of the same name.  This is just a more complicated version of the
933
   * above mkMutualDatatypeTypes() function, but is required to handle
934
   * complex types.
935
   *
936
   * For example, unresolvedTypes might contain the single sort "list"
937
   * (with that name reported from SortType::getName()).  The
938
   * datatypes list might have the single datatype
939
   *
940
   *   DATATYPE
941
   *     list = cons(car:ARRAY INT OF list, cdr:list) | nil;
942
   *   END;
943
   *
944
   * To represent the Type of the array, the user had to create a
945
   * placeholder type (an uninterpreted sort) to stand for "list" in
946
   * the type of "car".  It is this placeholder sort that should be
947
   * passed in unresolvedTypes.  If the datatype was of the simpler
948
   * form:
949
   *
950
   *   DATATYPE
951
   *     list = cons(car:list, cdr:list) | nil;
952
   *   END;
953
   *
954
   * then no complicated Type needs to be created, and the above,
955
   * simpler form of mkMutualDatatypeTypes() is enough.
956
   */
957
  std::vector<TypeNode> mkMutualDatatypeTypes(
958
      const std::vector<DType>& datatypes,
959
      const std::set<TypeNode>& unresolvedTypes,
960
      uint32_t flags = DATATYPE_FLAG_NONE);
961
962
  /**
963
   * Make a type representing a constructor with the given argument (subfield)
964
   * types and return type range.
965
   */
966
  TypeNode mkConstructorType(const std::vector<TypeNode>& args, TypeNode range);
967
968
  /** Make a type representing a selector with the given parameterization */
969
  TypeNode mkSelectorType(TypeNode domain, TypeNode range);
970
971
  /** Make a type representing a tester with given parameterization */
972
  TypeNode mkTesterType(TypeNode domain);
973
974
  /** Make a type representing an updater with the given parameterization */
975
  TypeNode mkDatatypeUpdateType(TypeNode domain, TypeNode range);
976
977
  /** Bits for use in mkSort() flags. */
978
  enum
979
  {
980
    SORT_FLAG_NONE = 0,
981
    SORT_FLAG_PLACEHOLDER = 1
982
  }; /* enum */
983
984
  /** Make a new (anonymous) sort of arity 0. */
985
  TypeNode mkSort(uint32_t flags = SORT_FLAG_NONE);
986
987
  /** Make a new sort with the given name of arity 0. */
988
  TypeNode mkSort(const std::string& name, uint32_t flags = SORT_FLAG_NONE);
989
990
  /** Make a new sort by parameterizing the given sort constructor. */
991
  TypeNode mkSort(TypeNode constructor,
992
                  const std::vector<TypeNode>& children,
993
                  uint32_t flags = SORT_FLAG_NONE);
994
995
  /** Make a new sort with the given name and arity. */
996
  TypeNode mkSortConstructor(const std::string& name,
997
                             size_t arity,
998
                             uint32_t flags = SORT_FLAG_NONE);
999
1000
  /**
1001
   * Get the type for the given node and optionally do type checking.
1002
   *
1003
   * Initial type computation will be near-constant time if
1004
   * type checking is not requested. Results are memoized, so that
1005
   * subsequent calls to getType() without type checking will be
1006
   * constant time.
1007
   *
1008
   * Initial type checking is linear in the size of the expression.
1009
   * Again, the results are memoized, so that subsequent calls to
1010
   * getType(), with or without type checking, will be constant
1011
   * time.
1012
   *
1013
   * NOTE: A TypeCheckingException can be thrown even when type
1014
   * checking is not requested. getType() will always return a
1015
   * valid and correct type and, thus, an exception will be thrown
1016
   * when no valid or correct type can be computed (e.g., if the
1017
   * arguments to a bit-vector operation aren't bit-vectors). When
1018
   * type checking is not requested, getType() will do the minimum
1019
   * amount of checking required to return a valid result.
1020
   *
1021
   * @param n the Node for which we want a type
1022
   * @param check whether we should check the type as we compute it
1023
   * (default: false)
1024
   */
1025
  TypeNode getType(TNode n, bool check = false);
1026
1027
  /** Reclaim zombies while there are more than k nodes in the pool (if possible).*/
1028
  void reclaimZombiesUntil(uint32_t k);
1029
1030
  /** Reclaims all zombies (if possible).*/
1031
  void reclaimAllZombies();
1032
1033
  /** Size of the node pool. */
1034
  size_t poolSize() const;
1035
1036
  /** Deletes a list of attributes from the NM's AttributeManager.*/
1037
  void deleteAttributes(const std::vector< const expr::attr::AttributeUniqueId* >& ids);
1038
1039
  /**
1040
   * This function gives developers a hook into the NodeManager.
1041
   * This can be changed in node_manager.cpp without recompiling most of cvc5.
1042
   *
1043
   * debugHook is a debugging only function, and should not be present in
1044
   * any published code!
1045
   */
1046
  void debugHook(int debugFlag);
1047
}; /* class NodeManager */
1048
1049
/**
1050
 * This class changes the "current" thread-global
1051
 * <code>NodeManager</code> when it is created and reinstates the
1052
 * previous thread-global <code>NodeManager</code> when it is
1053
 * destroyed, effectively maintaining a set of nested
1054
 * <code>NodeManager</code> scopes.  This is especially useful on
1055
 * public-interface calls into the cvc5 library, where cvc5's notion
1056
 * of the "current" <code>NodeManager</code> should be set to match
1057
 * the calling context.  See, for example, the implementations of
1058
 * public calls in the <code>SmtEngine</code> class.
1059
 *
1060
 * The client must be careful to create and destroy
1061
 * <code>NodeManagerScope</code> objects in a well-nested manner (such
1062
 * as on the stack). You may create a <code>NodeManagerScope</code>
1063
 * with <code>new</code> and destroy it with <code>delete</code>, or
1064
 * place it as a data member of an object that is, but if the scope of
1065
 * these <code>new</code>/<code>delete</code> pairs isn't properly
1066
 * maintained, the incorrect "current" <code>NodeManager</code>
1067
 * pointer may be restored after a delete.
1068
 */
1069
class NodeManagerScope {
1070
  /** The old NodeManager, to be restored on destruction. */
1071
  NodeManager* d_oldNodeManager;
1072
public:
1073
965717028
 NodeManagerScope(NodeManager* nm) : d_oldNodeManager(NodeManager::s_current)
1074
 {
1075
965717028
   NodeManager::s_current = nm;
1076
965717028
   Debug("current") << "node manager scope: " << NodeManager::s_current << "\n";
1077
965717028
  }
1078
1079
1931434056
  ~NodeManagerScope() {
1080
965717028
    NodeManager::s_current = d_oldNodeManager;
1081
1931434056
    Debug("current") << "node manager scope: "
1082
965717028
                     << "returning to " << NodeManager::s_current << "\n";
1083
965717028
  }
1084
};/* class NodeManagerScope */
1085
1086
10445
inline TypeNode NodeManager::mkArrayType(TypeNode indexType,
1087
                                         TypeNode constituentType) {
1088
10445
  CheckArgument(!indexType.isNull(), indexType,
1089
                "unexpected NULL index type");
1090
10445
  CheckArgument(!constituentType.isNull(), constituentType,
1091
                "unexpected NULL constituent type");
1092
10445
  CheckArgument(indexType.isFirstClass(),
1093
                indexType,
1094
                "cannot index arrays by types that are not first-class. Try "
1095
                "option --uf-ho.");
1096
10445
  CheckArgument(constituentType.isFirstClass(),
1097
                constituentType,
1098
                "cannot store types that are not first-class in arrays. Try "
1099
                "option --uf-ho.");
1100
20890
  Debug("arrays") << "making array type " << indexType << " "
1101
10445
                  << constituentType << std::endl;
1102
10445
  return mkTypeNode(kind::ARRAY_TYPE, indexType, constituentType);
1103
}
1104
1105
12916
inline TypeNode NodeManager::mkSetType(TypeNode elementType) {
1106
12916
  CheckArgument(!elementType.isNull(), elementType,
1107
                "unexpected NULL element type");
1108
12916
  CheckArgument(elementType.isFirstClass(),
1109
                elementType,
1110
                "cannot store types that are not first-class in sets. Try "
1111
                "option --uf-ho.");
1112
12916
  Debug("sets") << "making sets type " << elementType << std::endl;
1113
12916
  return mkTypeNode(kind::SET_TYPE, elementType);
1114
}
1115
1116
432298478
inline expr::NodeValue* NodeManager::poolLookup(expr::NodeValue* nv) const {
1117
432298478
  NodeValuePool::const_iterator find = d_nodeValuePool.find(nv);
1118
432298478
  if(find == d_nodeValuePool.end()) {
1119
27633253
    return NULL;
1120
  } else {
1121
404665225
    return *find;
1122
  }
1123
}
1124
1125
27640772
inline void NodeManager::poolInsert(expr::NodeValue* nv) {
1126
27640772
  Assert(d_nodeValuePool.find(nv) == d_nodeValuePool.end())
1127
      << "NodeValue already in the pool!";
1128
27640772
  d_nodeValuePool.insert(nv);// FIXME multithreading
1129
27640772
}
1130
1131
27640772
inline void NodeManager::poolRemove(expr::NodeValue* nv) {
1132
27640772
  Assert(d_nodeValuePool.find(nv) != d_nodeValuePool.end())
1133
      << "NodeValue is not in the pool!";
1134
1135
27640772
  d_nodeValuePool.erase(nv);// FIXME multithreading
1136
27640772
}
1137
1138
}  // namespace cvc5
1139
1140
#define CVC5__NODE_MANAGER_NEEDS_CONSTANT_MAP
1141
#include "expr/metakind.h"
1142
#undef CVC5__NODE_MANAGER_NEEDS_CONSTANT_MAP
1143
1144
#include "expr/node_builder.h"
1145
1146
namespace cvc5 {
1147
1148
// general expression-builders
1149
1150
17002561
inline bool NodeManager::hasOperator(Kind k) {
1151
17002561
  switch(kind::MetaKind mk = kind::metaKindOf(k)) {
1152
1153
1924561
  case kind::metakind::INVALID:
1154
  case kind::metakind::VARIABLE:
1155
  case kind::metakind::NULLARY_OPERATOR:
1156
1924561
    return false;
1157
1158
13323027
  case kind::metakind::OPERATOR:
1159
  case kind::metakind::PARAMETERIZED:
1160
13323027
    return true;
1161
1162
1754973
  case kind::metakind::CONSTANT:
1163
1754973
    return false;
1164
1165
  default: Unhandled() << mk;
1166
  }
1167
}
1168
1169
576599
inline Kind NodeManager::operatorToKind(TNode n) {
1170
576599
  return kind::operatorToKind(n.d_nv);
1171
}
1172
1173
49508086
inline Node NodeManager::mkNode(Kind kind, TNode child1) {
1174
99016172
  NodeBuilder nb(this, kind);
1175
49508086
  nb << child1;
1176
99016160
  return nb.constructNode();
1177
}
1178
1179
107028604
inline Node NodeManager::mkNode(Kind kind, TNode child1, TNode child2) {
1180
214057208
  NodeBuilder nb(this, kind);
1181
107028604
  nb << child1 << child2;
1182
214056834
  return nb.constructNode();
1183
}
1184
1185
826025
inline Node NodeManager::mkNode(Kind kind, TNode child1, TNode child2,
1186
                                TNode child3) {
1187
1652050
  NodeBuilder nb(this, kind);
1188
826025
  nb << child1 << child2 << child3;
1189
1652018
  return nb.constructNode();
1190
}
1191
1192
1186
inline Node NodeManager::mkNode(Kind kind, TNode child1, TNode child2,
1193
                                TNode child3, TNode child4) {
1194
2372
  NodeBuilder nb(this, kind);
1195
1186
  nb << child1 << child2 << child3 << child4;
1196
2372
  return nb.constructNode();
1197
}
1198
1199
28
inline Node NodeManager::mkNode(Kind kind, TNode child1, TNode child2,
1200
                                TNode child3, TNode child4, TNode child5) {
1201
56
  NodeBuilder nb(this, kind);
1202
28
  nb << child1 << child2 << child3 << child4 << child5;
1203
56
  return nb.constructNode();
1204
}
1205
1206
// N-ary version
1207
template <bool ref_count>
1208
14733742
inline Node NodeManager::mkNode(Kind kind,
1209
                                const std::vector<NodeTemplate<ref_count> >&
1210
                                children) {
1211
29467484
  NodeBuilder nb(this, kind);
1212
14733742
  nb.append(children);
1213
29467455
  return nb.constructNode();
1214
}
1215
1216
template <bool ref_count>
1217
649052
Node NodeManager::mkAnd(const std::vector<NodeTemplate<ref_count> >& children)
1218
{
1219
649052
  if (children.empty())
1220
  {
1221
34841
    return mkConst(true);
1222
  }
1223
614211
  else if (children.size() == 1)
1224
  {
1225
394805
    return children[0];
1226
  }
1227
219406
  return mkNode(kind::AND, children);
1228
}
1229
1230
template <bool ref_count>
1231
Node NodeManager::mkOr(const std::vector<NodeTemplate<ref_count> >& children)
1232
{
1233
  if (children.empty())
1234
  {
1235
    return mkConst(false);
1236
  }
1237
  else if (children.size() == 1)
1238
  {
1239
    return children[0];
1240
  }
1241
  return mkNode(kind::OR, children);
1242
}
1243
1244
// for operators
1245
inline Node NodeManager::mkNode(TNode opNode) {
1246
  NodeBuilder nb(this, operatorToKind(opNode));
1247
  if(opNode.getKind() != kind::BUILTIN) {
1248
    nb << opNode;
1249
  }
1250
  return nb.constructNode();
1251
}
1252
1253
257349
inline Node NodeManager::mkNode(TNode opNode, TNode child1) {
1254
514698
  NodeBuilder nb(this, operatorToKind(opNode));
1255
257349
  if(opNode.getKind() != kind::BUILTIN) {
1256
257349
    nb << opNode;
1257
  }
1258
257349
  nb << child1;
1259
514698
  return nb.constructNode();
1260
}
1261
1262
64
inline Node NodeManager::mkNode(TNode opNode, TNode child1, TNode child2) {
1263
128
  NodeBuilder nb(this, operatorToKind(opNode));
1264
64
  if(opNode.getKind() != kind::BUILTIN) {
1265
64
    nb << opNode;
1266
  }
1267
64
  nb << child1 << child2;
1268
128
  return nb.constructNode();
1269
}
1270
1271
inline Node NodeManager::mkNode(TNode opNode, TNode child1, TNode child2,
1272
                                TNode child3) {
1273
  NodeBuilder nb(this, operatorToKind(opNode));
1274
  if(opNode.getKind() != kind::BUILTIN) {
1275
    nb << opNode;
1276
  }
1277
  nb << child1 << child2 << child3;
1278
  return nb.constructNode();
1279
}
1280
1281
inline Node NodeManager::mkNode(TNode opNode, TNode child1, TNode child2,
1282
                                TNode child3, TNode child4) {
1283
  NodeBuilder nb(this, operatorToKind(opNode));
1284
  if(opNode.getKind() != kind::BUILTIN) {
1285
    nb << opNode;
1286
  }
1287
  nb << child1 << child2 << child3 << child4;
1288
  return nb.constructNode();
1289
}
1290
1291
inline Node NodeManager::mkNode(TNode opNode, TNode child1, TNode child2,
1292
                                TNode child3, TNode child4, TNode child5) {
1293
  NodeBuilder nb(this, operatorToKind(opNode));
1294
  if(opNode.getKind() != kind::BUILTIN) {
1295
    nb << opNode;
1296
  }
1297
  nb << child1 << child2 << child3 << child4 << child5;
1298
  return nb.constructNode();
1299
}
1300
1301
// N-ary version for operators
1302
template <bool ref_count>
1303
46635
inline Node NodeManager::mkNode(TNode opNode,
1304
                                const std::vector<NodeTemplate<ref_count> >&
1305
                                children) {
1306
93270
  NodeBuilder nb(this, operatorToKind(opNode));
1307
46635
  if(opNode.getKind() != kind::BUILTIN) {
1308
866
    nb << opNode;
1309
  }
1310
46635
  nb.append(children);
1311
93270
  return nb.constructNode();
1312
}
1313
1314
29056
inline TypeNode NodeManager::mkTypeNode(Kind kind, TypeNode child1) {
1315
29056
  return (NodeBuilder(this, kind) << child1).constructTypeNode();
1316
}
1317
1318
43030
inline TypeNode NodeManager::mkTypeNode(Kind kind, TypeNode child1,
1319
                                        TypeNode child2) {
1320
43030
  return (NodeBuilder(this, kind) << child1 << child2).constructTypeNode();
1321
}
1322
1323
inline TypeNode NodeManager::mkTypeNode(Kind kind, TypeNode child1,
1324
                                        TypeNode child2, TypeNode child3) {
1325
  return (NodeBuilder(this, kind) << child1 << child2 << child3)
1326
      .constructTypeNode();
1327
}
1328
1329
// N-ary version for types
1330
72682
inline TypeNode NodeManager::mkTypeNode(Kind kind,
1331
                                        const std::vector<TypeNode>& children) {
1332
72682
  return NodeBuilder(this, kind).append(children).constructTypeNode();
1333
}
1334
1335
template <class T>
1336
189573137
Node NodeManager::mkConst(const T& val) {
1337
189573137
  return mkConstInternal<Node, T>(val);
1338
}
1339
1340
template <class T>
1341
28939327
TypeNode NodeManager::mkTypeConst(const T& val) {
1342
28939327
  return mkConstInternal<TypeNode, T>(val);
1343
}
1344
1345
template <class NodeClass, class T>
1346
218512464
NodeClass NodeManager::mkConstInternal(const T& val) {
1347
  // This method indirectly calls `NodeValue::inc()`, which relies on having
1348
  // the correct `NodeManager` in scope.
1349
437024928
  NodeManagerScope nms(this);
1350
1351
  // typedef typename kind::metakind::constantMap<T>::OwningTheory theory_t;
1352
218512464
  NVStorage<1> nvStorage;
1353
218512464
  expr::NodeValue& nvStack = reinterpret_cast<expr::NodeValue&>(nvStorage);
1354
1355
218512464
  nvStack.d_id = 0;
1356
218512464
  nvStack.d_kind = kind::metakind::ConstantMap<T>::kind;
1357
218512464
  nvStack.d_rc = 0;
1358
218512464
  nvStack.d_nchildren = 1;
1359
1360
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1361
#pragma GCC diagnostic push
1362
#pragma GCC diagnostic ignored "-Warray-bounds"
1363
#endif
1364
1365
218512464
  nvStack.d_children[0] =
1366
    const_cast<expr::NodeValue*>(reinterpret_cast<const expr::NodeValue*>(&val));
1367
218512464
  expr::NodeValue* nv = poolLookup(&nvStack);
1368
1369
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
1370
#pragma GCC diagnostic pop
1371
#endif
1372
1373
218512464
  if(nv != NULL) {
1374
215967533
    return NodeClass(nv);
1375
  }
1376
1377
2544931
  nv = (expr::NodeValue*)
1378
2544931
    std::malloc(sizeof(expr::NodeValue) + sizeof(T));
1379
2544931
  if(nv == NULL) {
1380
    throw std::bad_alloc();
1381
  }
1382
1383
2544931
  nv->d_nchildren = 0;
1384
2544931
  nv->d_kind = kind::metakind::ConstantMap<T>::kind;
1385
2544931
  nv->d_id = next_id++;// FIXME multithreading
1386
2544931
  nv->d_rc = 0;
1387
1388
  //OwningTheory::mkConst(val);
1389
2544931
  new (&nv->d_children) T(val);
1390
1391
2544931
  poolInsert(nv);
1392
2544931
  if(Debug.isOn("gc")) {
1393
    Debug("gc") << "creating node value " << nv
1394
                << " [" << nv->d_id << "]: ";
1395
    nv->printAst(Debug("gc"));
1396
    Debug("gc") << std::endl;
1397
  }
1398
1399
2544931
  return NodeClass(nv);
1400
}
1401
1402
}  // namespace cvc5
1403
1404
#endif /* CVC5__NODE_MANAGER_H */