GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/node_manager.h Lines: 145 160 90.6 %
Date: 2021-11-07 Branches: 511 1940 26.3 %

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