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