GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node_manager.h Lines: 163 182 89.6 %
Date: 2021-09-29 Branches: 507 1936 26.2 %

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