GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node_manager.h Lines: 174 193 90.2 %
Date: 2021-08-20 Branches: 541 2012 26.9 %

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