GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/dtype.h Lines: 1 2 50.0 %
Date: 2021-05-22 Branches: 18 40 45.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Tim King
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 class representing a datatype definition.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__EXPR__DTYPE_H
19
#define CVC5__EXPR__DTYPE_H
20
21
#include <map>
22
#include <string>
23
#include <vector>
24
#include "expr/attribute.h"
25
#include "expr/node.h"
26
#include "expr/type_node.h"
27
28
namespace cvc5 {
29
30
// ----------------------- datatype attributes
31
/**
32
 * Attribute for the index of an expression within a datatype, which is either:
33
 * (1) If the expression is a constructor, then its index refers to its
34
 * placement in the constructor list of the datatype that owns it, (2) If the
35
 * expression is a selector, then its index refers to its placement in the
36
 * argument list of the constructor that owns it.
37
 */
38
struct DTypeIndexTag
39
{
40
};
41
typedef expr::Attribute<DTypeIndexTag, size_t> DTypeIndexAttr;
42
/**
43
 * Attribute for the constructor index of a selector. This indicates the index
44
 * (DTypeIndexAttr) of the constructor that owns this selector.
45
 */
46
struct DTypeConsIndexTag
47
{
48
};
49
typedef expr::Attribute<DTypeConsIndexTag, size_t> DTypeConsIndexAttr;
50
// ----------------------- end datatype attributes
51
52
class DTypeConstructor;
53
54
/**
55
 * The Node-level representation of an inductive datatype, which currently
56
 * resides within the Expr-level Datatype class (expr/datatype.h).
57
 *
58
 * Notice that this class is a specification for a datatype, and is not
59
 * itself a type. The type that this specification corresponds to can be
60
 * retrieved (after resolution as described in the following) via getTypeNode.
61
 *
62
 * This is far more complicated than it first seems.  Consider this
63
 * datatype definition:
64
 *
65
 *   DATATYPE nat =
66
 *     succ(pred: nat)
67
 *   | zero
68
 *   END;
69
 *
70
 * You cannot define "nat" until you have a Type for it, but you
71
 * cannot have a Type for it until you fill in the type of the "pred"
72
 * selector, which needs the Type.  So we have a chicken-and-egg
73
 * problem.  It's even more complicated when we have mutual recursion
74
 * between datatypes, since the CVC presentation language does not
75
 * require forward-declarations.  Here, we define trees of lists that
76
 * contain trees of lists (etc):
77
 *
78
 *   DATATYPE
79
 *     tree = node(left: tree, right: tree) | leaf(list),
80
 *     list = cons(car: tree, cdr: list) | nil
81
 *   END;
82
 *
83
 * We build DType objects to describe "tree" and "list", and their constructors
84
 * and constructor arguments, but leave any unknown types (including
85
 * self-references) in an "unresolved" state.  After parsing the whole DATATYPE
86
 * block, we create a TypeNode through ExprManager::mkMutualDatatypeTypes().
87
 * The ExprManager creates a Type for each, but before "releasing" this type
88
 * into the wild, it does a round of in-place "resolution" on each DType by
89
 * calling DType::resolve() with a map of string -> TypeNode to
90
 * allow the datatype to construct the necessary testers and selectors.
91
 *
92
 * An additional point to make is that we want to ease the burden on
93
 * both the parser AND the users of the cvc5 API, so this class takes
94
 * on the task of generating its own selectors and testers, for
95
 * instance.  That means that, after reifying the DType with the
96
 * NodeManager, the parser needs to go through the (now-resolved)
97
 * DType and request the constructor, selector, and tester terms.
98
 * See src/parser/parser.cpp for how this is done.  For API usage
99
 * ideas, see test/unit/util/datatype_black.h.
100
 *
101
 * DTypes may also be defined parametrically, such as this example:
102
 *
103
 *  DATATYPE
104
 *    list[T] = cons(car : T, cdr : list[T]) | null,
105
 *    tree = node(children : list[tree]) | leaf
106
 *  END;
107
 *
108
 * Here, the definition of the parametric datatype list, where T is a type
109
 * variable. In other words, this defines a family of types list[C] where C is
110
 * any concrete type.  DTypes can be parameterized over multiple type variables
111
 * using the syntax sym[ T1, ..., Tn ] = ...,
112
 *
113
 */
114
19589
class DType
115
{
116
  friend class DTypeConstructor;
117
  friend class NodeManager;  // for access to resolve()
118
119
 public:
120
  /**
121
   * Get the datatype of a constructor, selector, or tester operator.
122
   */
123
  static const DType& datatypeOf(Node item);
124
125
  /**
126
   * Get the index of a constructor or tester in its datatype, or the
127
   * index of a selector in its constructor.  (Zero is always the
128
   * first index.)
129
   */
130
  static size_t indexOf(Node item);
131
132
  /**
133
   * Get the index of constructor corresponding to selector.  (Zero is
134
   * always the first index.)
135
   */
136
  static size_t cindexOf(Node item);
137
138
  /**
139
   * Same as above, but without checks. These methods should be used by
140
   * internal (Node-level) code.
141
   */
142
  static size_t indexOfInternal(Node item);
143
  static size_t cindexOfInternal(Node item);
144
145
  /** Create a new DType of the given name. */
146
  DType(std::string name, bool isCo = false);
147
148
  /**
149
   * Create a new DType of the given name, with the given
150
   * parameterization.
151
   */
152
  DType(std::string name,
153
        const std::vector<TypeNode>& params,
154
        bool isCo = false);
155
156
  ~DType();
157
158
  /** Add a constructor to this DType.
159
   *
160
   * Notice that constructor names need not
161
   * be unique; they are for convenience and pretty-printing only.
162
   */
163
  void addConstructor(std::shared_ptr<DTypeConstructor> c);
164
  /** add sygus constructor
165
   *
166
   * This adds a sygus constructor to this datatype, where
167
   * this datatype should be currently unresolved. Note this method is
168
   * syntactic sugar for adding a normal constructor and setting it to be a
169
   * sygus constructor, and following a naming convention that avoids
170
   * constructors with the same name.
171
   *
172
   * @param op : the builtin operator, constant, or variable that this
173
   * constructor encodes
174
   * @param cname the name of the constructor (for printing only)
175
   * @param cargs the arguments of the constructor.
176
   * It should be the case that cargs are sygus datatypes that
177
   * encode the arguments of op. For example, a sygus constructor
178
   * with op = PLUS should be such that cargs.size()>=2 and
179
   * the sygus type of cargs[i] is Real/Int for each i.
180
   * @param weight denotes the value added by the constructor when computing the
181
   * size of datatype terms. Passing a value < 0 denotes the default weight for
182
   * the constructor, which is 0 for nullary constructors and 1 for non-nullary
183
   * constructors.
184
   */
185
  void addSygusConstructor(Node op,
186
                           const std::string& cname,
187
                           const std::vector<TypeNode>& cargs,
188
                           int weight = -1);
189
190
  /** set sygus
191
   *
192
   * This marks this datatype as a sygus datatype.
193
   * A sygus datatype is one that represents terms of type st
194
   * via a deep embedding described in Section 4 of
195
   * Reynolds et al. CAV 2015. We say that this sygus datatype
196
   * "encodes" its sygus type st in the following.
197
   *
198
   * st : the type this datatype encodes (this can be Int, Bool, etc.),
199
   * bvl : the list of arguments for the synth-fun
200
   * allow_const : whether all constants are (implicitly) allowed by the
201
   * datatype
202
   * allow_all : whether all terms are (implicitly) allowed by the datatype
203
   *
204
   * Notice that allow_const/allow_all do not reflect the constructors
205
   * for this datatype, and instead are used solely for relaxing constraints
206
   * when doing solution reconstruction (Figure 5 of Reynolds et al.
207
   * CAV 2015).
208
   */
209
  void setSygus(TypeNode st, Node bvl, bool allowConst, bool allowAll);
210
211
  /** set that this datatype is a tuple */
212
  void setTuple();
213
214
  /** set that this datatype is a record */
215
  void setRecord();
216
217
  /** Get the name of this DType. */
218
  std::string getName() const;
219
220
  /** Get the number of constructors (so far) for this DType. */
221
  size_t getNumConstructors() const;
222
223
  /** Is this datatype parametric? */
224
  bool isParametric() const;
225
226
  /** Get the number of type parameters */
227
  size_t getNumParameters() const;
228
229
  /** Get parameter */
230
  TypeNode getParameter(size_t i) const;
231
232
  /** Get parameters */
233
  std::vector<TypeNode> getParameters() const;
234
235
  /** is this a co-datatype? */
236
  bool isCodatatype() const;
237
238
  /** is this a sygus datatype? */
239
  bool isSygus() const;
240
241
  /** is this a tuple datatype? */
242
  bool isTuple() const;
243
244
  /** is this a record datatype? */
245
  bool isRecord() const;
246
247
  /**
248
   * Return the cardinality of this datatype.
249
   * The DType must be resolved.
250
   *
251
   * The version of this method that takes type t is required
252
   * for parametric datatypes, where t is an instantiated
253
   * parametric datatype type whose datatype is this class.
254
   */
255
  Cardinality getCardinality(TypeNode t) const;
256
  Cardinality getCardinality() const;
257
258
  /**
259
   * Return the cardinality class of the datatype. The
260
   * DType must be resolved or an assertion is violated.
261
   *
262
   * The version of this method that takes type t is required
263
   * for parametric datatypes, where t is an instantiated
264
   * parametric datatype type whose datatype is this class.
265
   */
266
  CardinalityClass getCardinalityClass(TypeNode t) const;
267
  CardinalityClass getCardinalityClass() const;
268
269
  /**
270
   * Return true iff this DType has finite cardinality. If the
271
   * datatype is not well-founded, this method returns false. The
272
   * DType must be resolved or an assertion is violated.
273
   *
274
   * The version of this method that takes type t is required
275
   * for parametric datatypes, where t is an instantiated
276
   * parametric datatype type whose datatype is this class.
277
   *
278
   * @param t The (instantiated) datatype type we are computing finiteness for
279
   * @param fmfEnabled Whether finite model finding is enabled
280
   * @return true if finite model finding is enabled
281
   */
282
  bool isFinite(TypeNode t, bool fmfEnabled=false) const;
283
  bool isFinite(bool fmfEnabled=false) const;
284
285
  /** is well-founded
286
   *
287
   * Return true iff this datatype is well-founded (there exist finite
288
   * values of this type). This datatype must be resolved or an assertion is
289
   * violated.
290
   */
291
  bool isWellFounded() const;
292
  /**
293
   * Does this datatype have nested recursion? This is true if this datatype
294
   * definition contains itself as an alien subfield type, or a variant
295
   * of itself as an alien subfield type (if this datatype is parametric).
296
   * For details see getAlienSubfieldTypes below.
297
   *
298
   * Notice that a type having no nested recursion may have a subfield type that
299
   * has nested recursion.
300
   */
301
  bool hasNestedRecursion() const;
302
303
  /** is recursive singleton
304
   *
305
   * Return true iff this datatype is a recursive singleton
306
   * (a recursive singleton is a recursive datatype with only
307
   * one infinite value). For details, see Reynolds et al. CADE 2015.
308
   *
309
   * The versions of these methods that takes type t is required
310
   * for parametric datatypes, where t is an instantiated
311
   * parametric datatype type whose datatype is this class.
312
   */
313
  bool isRecursiveSingleton(TypeNode t) const;
314
  bool isRecursiveSingleton() const;
315
316
  /** recursive single arguments
317
   *
318
   * Get recursive singleton argument types (uninterpreted sorts that the
319
   * cardinality of this datatype is dependent upon). For example, for :
320
   *   stream :=  cons( head1 : U1, head2 : U2, tail : stream )
321
   * Then, the recursive singleton argument types of stream are { U1, U2 },
322
   * since if U1 and U2 have cardinality one, then stream has cardinality
323
   * one as well.
324
   *
325
   * The versions of these methods that takes Type t is required
326
   * for parametric datatypes, where t is an instantiated
327
   * parametric datatype type whose datatype is this class.
328
   */
329
  unsigned getNumRecursiveSingletonArgTypes(TypeNode t) const;
330
  TypeNode getRecursiveSingletonArgType(TypeNode t, size_t i) const;
331
  unsigned getNumRecursiveSingletonArgTypes() const;
332
  TypeNode getRecursiveSingletonArgType(size_t i) const;
333
334
  /**
335
   * Construct and return a ground term of this DType.  The
336
   * DType must be both resolved and well-founded, or else an
337
   * exception is thrown.
338
   *
339
   * This method takes a type t, which is a datatype type whose
340
   * datatype is this class, which may be an instantiated datatype
341
   * type if this datatype is parametric.
342
   */
343
  Node mkGroundTerm(TypeNode t) const;
344
  /** Make ground value
345
   *
346
   * Same as above, but constructs a constant value instead of a ground term.
347
   * These two notions typically coincide. However, for uninterpreted sorts,
348
   * they do not: mkGroundTerm returns a fresh variable whereas mkValue returns
349
   * an uninterpreted constant. The motivation for mkGroundTerm is that
350
   * unintepreted constants should never appear in lemmas. The motivation for
351
   * mkGroundValue is for things like type enumeration and model construction.
352
   */
353
  Node mkGroundValue(TypeNode t) const;
354
355
  /**
356
   * Get the TypeNode associated to this DType.  Can only be
357
   * called post-resolution.
358
   */
359
  TypeNode getTypeNode() const;
360
361
  /**
362
   * Get the TypeNode associated to this (parameterized) DType.  Can only be
363
   * called post-resolution.
364
   */
365
  TypeNode getTypeNode(const std::vector<TypeNode>& params) const;
366
367
  /** Return true iff this DType has already been resolved. */
368
  bool isResolved() const;
369
370
  /** Get the ith DTypeConstructor. */
371
  const DTypeConstructor& operator[](size_t index) const;
372
373
  /** get sygus type
374
   * This gets the built-in type associated with
375
   * this sygus datatype, i.e. the type of the
376
   * term that this sygus datatype encodes.
377
   */
378
  TypeNode getSygusType() const;
379
380
  /** get sygus var list
381
   * This gets the variable list of the function
382
   * to synthesize using this sygus datatype.
383
   * For example, if we are synthesizing a binary
384
   * function f where solutions are of the form:
385
   *   f = (lambda (xy) t[x,y])
386
   * In this case, this method returns the
387
   * bound variable list containing x and y.
388
   */
389
  Node getSygusVarList() const;
390
  /** get sygus allow constants
391
   *
392
   * Does this sygus datatype allow constants?
393
   * Notice that this is not a property of the
394
   * constructors of this datatype. Instead, it is
395
   * an auxiliary flag (provided in the call
396
   * to setSygus).
397
   */
398
  bool getSygusAllowConst() const;
399
  /** get sygus allow all
400
   *
401
   * Does this sygus datatype allow all terms?
402
   * Notice that this is not a property of the
403
   * constructors of this datatype. Instead, it is
404
   * an auxiliary flag (provided in the call
405
   * to setSygus).
406
   */
407
  bool getSygusAllowAll() const;
408
409
  /** involves external type
410
   * Get whether this datatype has a subfield
411
   * in any constructor that is not a datatype type.
412
   */
413
  bool involvesExternalType() const;
414
  /** involves uninterpreted type
415
   * Get whether this datatype has a subfield
416
   * in any constructor that is an uninterpreted type.
417
   */
418
  bool involvesUninterpretedType() const;
419
420
  /**
421
   * Get the list of constructors.
422
   */
423
  const std::vector<std::shared_ptr<DTypeConstructor> >& getConstructors()
424
      const;
425
426
  /** prints this datatype to stream */
427
  void toStream(std::ostream& out) const;
428
429
 private:
430
  /**
431
   * DTypes refer to themselves, recursively, and we have a
432
   * chicken-and-egg problem.  The TypeNode around the DType
433
   * cannot exist until the DType is finalized, and the DType
434
   * cannot refer to the TypeNode representing itself until it
435
   * exists.  resolve() is called by the NodeManager when a type is
436
   * ultimately requested of the DType specification (that is, when
437
   * NodeManager::mkTypeNode() or NodeManager::mkMutualTypeNodes()
438
   * is called).  Has the effect of freezing the object, too; that is,
439
   * addConstructor() will fail after a call to resolve().
440
   *
441
   * The basic goal of resolution is to assign constructors, selectors,
442
   * and testers.  To do this, any UnresolvedType/SelfType references
443
   * must be cleared up.  This is the purpose of the "resolutions" map;
444
   * it includes any mutually-recursive datatypes that are currently
445
   * under resolution.  The four vectors come in two pairs (so, really
446
   * they are two maps).  placeholders->replacements give type variables
447
   * that should be resolved in the case of parametric datatypes.
448
   *
449
   * @param em the NodeManager at play
450
   * @param resolutions a map of strings to TypeNodes currently under
451
   * resolution
452
   * @param placeholders the types in these DTypes under resolution that must
453
   * be replaced
454
   * @param replacements the corresponding replacements
455
   * @param paramTypes the sort constructors in these DTypes under resolution
456
   * that must be replaced
457
   * @param paramReplacements the corresponding (parametric) TypeNodes
458
   */
459
  bool resolve(const std::map<std::string, TypeNode>& resolutions,
460
               const std::vector<TypeNode>& placeholders,
461
               const std::vector<TypeNode>& replacements,
462
               const std::vector<TypeNode>& paramTypes,
463
               const std::vector<TypeNode>& paramReplacements);
464
465
  /** compute the cardinality of this datatype */
466
  Cardinality computeCardinality(TypeNode t,
467
                                 std::vector<TypeNode>& processing) const;
468
  /** compute whether this datatype is a recursive singleton */
469
  bool computeCardinalityRecSingleton(TypeNode t,
470
                                      std::vector<TypeNode>& processing,
471
                                      std::vector<TypeNode>& u_assume) const;
472
  /** compute whether this datatype is well-founded */
473
  bool computeWellFounded(std::vector<TypeNode>& processing) const;
474
  /** compute ground term
475
   *
476
   * This method checks if there is a term of this datatype whose type is t
477
   * that is finitely constructable. As needed, it traverses its subfield types.
478
   *
479
   * The argument processing is the set of datatype types we are currently
480
   * traversing.
481
   *
482
   * The argument isValue is whether we are constructing a constant value. If
483
   * this flag is false, we are constructing a canonical ground term that is
484
   * not necessarily constant.
485
   */
486
  Node computeGroundTerm(TypeNode t,
487
                         std::vector<TypeNode>& processing,
488
                         bool isValue) const;
489
  /** Get the shared selector
490
   *
491
   * This returns the index^th (constructor-agnostic)
492
   * selector for type t. The type dtt is the datatype
493
   * type whose datatype is this class, where this may
494
   * be an instantiated parametric datatype.
495
   *
496
   * In the terminology of "DTypes with Shared Selectors",
497
   * this returns the term sel_{dtt}^{t,index}.
498
   */
499
  Node getSharedSelector(TypeNode dtt, TypeNode t, size_t index) const;
500
  /**
501
   * Helper for mkGroundTerm and mkGroundValue above.
502
   */
503
  Node mkGroundTermInternal(TypeNode t, bool isValue) const;
504
  /**
505
   * This method is used to get alien subfield types of this datatype.
506
   *
507
   * A subfield type T of a datatype type D is a type such that a value of
508
   * type T may appear as a subterm of a value of type D.
509
   *
510
   * An *alien* subfield type T of a datatype type D is a type such that a
511
   * value v of type T may appear as a subterm of a value of D, and moreover
512
   * v occurs as a strict subterm of a non-datatype term in that value.
513
   *
514
   * For example, the alien subfield types of T in:
515
   *   T -> Emp | Container(s : (Set List))
516
   *   List -> nil | cons( head : Int, tail: List)
517
   * are { List, Int }. Notice that Int is an alien subfield type since it
518
   * appears as a subfield type of List, and List is an alien subfield type
519
   * of T. In other words, Int is an alien subfield type due to the above
520
   * definition due to the term (Container (singleton (cons 0 nil))), where
521
   * 0 occurs as a subterm of (singleton (cons 0 nil)). The non-strict
522
   * subfield types of T in this example are { (Set List) }.
523
   *
524
   * For example, the alien subfield types of T in:
525
   *   T -> Emp | Container(s : List)
526
   *   List -> nil | cons( head : (Set T), tail: List)
527
   * are { T, List, (Set T) }. Notice that T is an alien subfield type of itself
528
   * since List is a subfield type of T and T is an alien subfield type of List.
529
   * Furthermore, List and (Set T) are also alien subfield types of T since
530
   * List is a subfield type of T and T is an alien subfield type of itself.
531
   *
532
   * For example, the alien subfield types of T in:
533
   *   T -> Emp | Container(s : (Array Int T))
534
   * are { T, Int }, where we assume that values of (Array U1 U2) are
535
   * constructed from values of U1 and U2, for all types U1, U2. The non-strict
536
   * subfield types of T in this example are { (Array Int T) }.
537
   *
538
   * @param types The set of types to append the alien subfield types to,
539
   * @param processed The datatypes (cached using d_self) we have processed. If
540
   * the range of this map is true, we have processed the datatype with
541
   * isAlienPos = true.
542
   * @param isAlienPos Whether we are in an alien subfield type position. This
543
   * flag is true if we have traversed beneath a non-datatype type constructor.
544
   */
545
  void getAlienSubfieldTypes(std::unordered_set<TypeNode>& types,
546
                             std::map<TypeNode, bool>& processed,
547
                             bool isAlienPos) const;
548
  /** name of this datatype */
549
  std::string d_name;
550
  /** the type parameters of this datatype (if this is a parametric datatype)
551
   */
552
  std::vector<TypeNode> d_params;
553
  /** whether the datatype is a codatatype. */
554
  bool d_isCo;
555
  /** whether the datatype is a tuple */
556
  bool d_isTuple;
557
  /** whether the datatype is a record */
558
  bool d_isRecord;
559
  /** the constructors of this datatype */
560
  std::vector<std::shared_ptr<DTypeConstructor> > d_constructors;
561
  /** whether this datatype has been resolved */
562
  bool d_resolved;
563
  /** self type */
564
  mutable TypeNode d_self;
565
  /** cache for involves external type */
566
  bool d_involvesExt;
567
  /** cache for involves uninterpreted type */
568
  bool d_involvesUt;
569
  /** the builtin type that this sygus type encodes */
570
  TypeNode d_sygusType;
571
  /** the variable list for the sygus function to synthesize */
572
  Node d_sygusBvl;
573
  /** whether all constants are allowed as solutions */
574
  bool d_sygusAllowConst;
575
  /** whether all terms are allowed as solutions */
576
  bool d_sygusAllowAll;
577
578
  /** the cardinality of this datatype
579
   * "mutable" because computing the cardinality can be expensive,
580
   * and so it's computed just once, on demand---this is the cache
581
   */
582
  mutable Cardinality d_card;
583
584
  /** is this type a recursive singleton type?
585
   * The range of this map stores
586
   * 0 if the field has not been computed,
587
   * 1 if this datatype is a recursive singleton type,
588
   * -1 if this datatype is not a recursive singleton type.
589
   * For definition of (co)recursive singleton, see
590
   * Section 2 of Reynolds et al. CADE 2015.
591
   */
592
  mutable std::map<TypeNode, int> d_cardRecSingleton;
593
  /** if d_cardRecSingleton is true,
594
   * This datatype has infinite cardinality if at least one of the
595
   * following uninterpreted sorts having cardinality > 1.
596
   */
597
  mutable std::map<TypeNode, std::vector<TypeNode> > d_cardUAssume;
598
  /**
599
   * Cache of whether this datatype is well-founded, where 0 means we have
600
   * not computed this information, 1 means it is well-founded, -1 means it is
601
   * not.
602
   */
603
  mutable int d_wellFounded;
604
  /**
605
   * Cache of whether this datatype has nested recursion, where 0 means we have
606
   * not computed this information, 1 means it has nested recursion, -1 means it
607
   * does not.
608
   */
609
  mutable int d_nestedRecursion;
610
  /** cache of ground term for this datatype */
611
  mutable std::map<TypeNode, Node> d_groundTerm;
612
  /** cache of ground values for this datatype */
613
  mutable std::map<TypeNode, Node> d_groundValue;
614
  /** cache of shared selectors for this datatype */
615
  mutable std::map<TypeNode, std::map<TypeNode, std::map<unsigned, Node> > >
616
      d_sharedSel;
617
  /**  A cache for getCardinalityClass. */
618
  mutable std::map<TypeNode, CardinalityClass> d_cardClass;
619
}; /* class DType */
620
621
/**
622
 * A hash function for DTypes.  Needed to store them in hash sets
623
 * and hash maps.
624
 */
625
struct DTypeHashFunction
626
{
627
  size_t operator()(const DType& dt) const
628
  {
629
    return std::hash<std::string>()(dt.getName());
630
  }
631
  size_t operator()(const DType* dt) const
632
  {
633
    return std::hash<std::string>()(dt->getName());
634
  }
635
}; /* struct DTypeHashFunction */
636
637
/* stores an index to DType residing in NodeManager */
638
class DTypeIndexConstant
639
{
640
 public:
641
  DTypeIndexConstant(size_t index);
642
643
  size_t getIndex() const { return d_index; }
644
  bool operator==(const DTypeIndexConstant& uc) const
645
  {
646
    return d_index == uc.d_index;
647
  }
648
  bool operator!=(const DTypeIndexConstant& uc) const { return !(*this == uc); }
649
  bool operator<(const DTypeIndexConstant& uc) const
650
  {
651
    return d_index < uc.d_index;
652
  }
653
  bool operator<=(const DTypeIndexConstant& uc) const
654
  {
655
    return d_index <= uc.d_index;
656
  }
657
  bool operator>(const DTypeIndexConstant& uc) const { return !(*this <= uc); }
658
  bool operator>=(const DTypeIndexConstant& uc) const { return !(*this < uc); }
659
660
 private:
661
  const size_t d_index;
662
}; /* class DTypeIndexConstant */
663
664
std::ostream& operator<<(std::ostream& out, const DTypeIndexConstant& dic);
665
666
struct DTypeIndexConstantHashFunction
667
{
668
  size_t operator()(const DTypeIndexConstant& dic) const
669
  {
670
    return IntegerHashFunction()(dic.getIndex());
671
  }
672
}; /* struct DTypeIndexConstantHashFunction */
673
674
std::ostream& operator<<(std::ostream& os, const DType& dt);
675
676
}  // namespace cvc5
677
678
#endif