1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Morgan Deters, Tim King, Andrew Reynolds |
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 |
|
* Enumerators for types. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__TYPE_ENUMERATOR_H |
19 |
|
#define CVC5__THEORY__TYPE_ENUMERATOR_H |
20 |
|
|
21 |
|
#include "base/check.h" |
22 |
|
#include "base/exception.h" |
23 |
|
#include "expr/node.h" |
24 |
|
#include "expr/type_node.h" |
25 |
|
#include "util/integer.h" |
26 |
|
|
27 |
|
namespace cvc5 { |
28 |
|
namespace theory { |
29 |
|
|
30 |
3183 |
class NoMoreValuesException : public Exception { |
31 |
|
public: |
32 |
3183 |
NoMoreValuesException(TypeNode n) |
33 |
3183 |
: Exception("No more values for type `" + n.toString() + "'") |
34 |
|
{ |
35 |
3183 |
} |
36 |
|
};/* class NoMoreValuesException */ |
37 |
|
|
38 |
5903 |
class TypeEnumeratorInterface { |
39 |
|
public: |
40 |
224863 |
TypeEnumeratorInterface(TypeNode type) : d_type(type) {} |
41 |
|
|
42 |
230766 |
virtual ~TypeEnumeratorInterface() {} |
43 |
|
|
44 |
|
/** Is this enumerator out of constants to enumerate? */ |
45 |
|
virtual bool isFinished() = 0; |
46 |
|
|
47 |
|
/** |
48 |
|
* Get the current constant of this type. |
49 |
|
* |
50 |
|
* @throws NoMoreValuesException if no such constant exists. |
51 |
|
*/ |
52 |
|
virtual Node operator*() = 0; |
53 |
|
|
54 |
|
/** Increment the pointer to the next available constant. */ |
55 |
|
virtual TypeEnumeratorInterface& operator++() = 0; |
56 |
|
|
57 |
|
/** Clone this enumerator. */ |
58 |
|
virtual TypeEnumeratorInterface* clone() const = 0; |
59 |
|
|
60 |
|
/** Get the type from which we're enumerating constants. */ |
61 |
27658 |
TypeNode getType() const { return d_type; } |
62 |
|
|
63 |
|
private: |
64 |
|
const TypeNode d_type; |
65 |
|
}; /* class TypeEnumeratorInterface */ |
66 |
|
|
67 |
|
/** |
68 |
|
* This class stores particular information that is relevant to type |
69 |
|
* enumeration. For finite model finding, we set d_fixed_usort=true, and store |
70 |
|
* the finite cardinality bounds for each uninterpreted sort encountered in the |
71 |
|
* model. For strings, we store the cardinality for the alphabet that we are |
72 |
|
* assuming. |
73 |
|
*/ |
74 |
24989 |
class TypeEnumeratorProperties |
75 |
|
{ |
76 |
|
public: |
77 |
24989 |
TypeEnumeratorProperties(bool fixUSortCard, uint32_t strAlphaCard) |
78 |
24989 |
: d_fixed_usort_card(fixUSortCard), d_stringAlphaCard(strAlphaCard) |
79 |
|
{ |
80 |
24989 |
} |
81 |
|
Integer getFixedCardinality(TypeNode tn) { return d_fixed_card[tn]; } |
82 |
|
bool d_fixed_usort_card; |
83 |
|
std::map<TypeNode, Integer> d_fixed_card; |
84 |
|
/** Get the alphabet for strings */ |
85 |
74 |
uint32_t getStringsAlphabetCard() const { return d_stringAlphaCard; } |
86 |
|
|
87 |
|
private: |
88 |
|
/** The cardinality of the alphabet */ |
89 |
|
uint32_t d_stringAlphaCard; |
90 |
|
}; |
91 |
|
|
92 |
|
template <class T> |
93 |
236669 |
class TypeEnumeratorBase : public TypeEnumeratorInterface { |
94 |
|
public: |
95 |
|
|
96 |
224863 |
TypeEnumeratorBase(TypeNode type) : |
97 |
224863 |
TypeEnumeratorInterface(type) { |
98 |
224863 |
} |
99 |
|
|
100 |
13585 |
TypeEnumeratorInterface* clone() const override |
101 |
|
{ |
102 |
13585 |
return new T(static_cast<const T&>(*this)); |
103 |
|
} |
104 |
|
|
105 |
|
};/* class TypeEnumeratorBase */ |
106 |
|
|
107 |
|
/** Type enumerator class. |
108 |
|
* Enumerates values for a type. |
109 |
|
* Its constructor takes the type to enumerate and a pointer to a |
110 |
|
* TypeEnumeratorProperties class, which this type enumerator does not own. |
111 |
|
*/ |
112 |
|
class TypeEnumerator { |
113 |
|
TypeEnumeratorInterface* d_te; |
114 |
|
|
115 |
|
static TypeEnumeratorInterface* mkTypeEnumerator( |
116 |
|
TypeNode type, TypeEnumeratorProperties* tep); |
117 |
|
|
118 |
|
public: |
119 |
217079 |
TypeEnumerator(TypeNode type, TypeEnumeratorProperties* tep = nullptr) |
120 |
217079 |
: d_te(mkTypeEnumerator(type, tep)) |
121 |
|
{ |
122 |
217079 |
} |
123 |
|
|
124 |
13583 |
TypeEnumerator(const TypeEnumerator& te) : |
125 |
13583 |
d_te(te.d_te->clone()) { |
126 |
13583 |
} |
127 |
78 |
TypeEnumerator(TypeEnumeratorInterface* te) : d_te(te){ |
128 |
78 |
} |
129 |
2 |
TypeEnumerator& operator=(const TypeEnumerator& te) { |
130 |
2 |
delete d_te; |
131 |
2 |
d_te = te.d_te->clone(); |
132 |
2 |
return *this; |
133 |
|
} |
134 |
|
|
135 |
230740 |
~TypeEnumerator() { delete d_te; } |
136 |
294323 |
bool isFinished() |
137 |
|
{ |
138 |
|
// On Mac clang, there appears to be a code generation bug in an exception |
139 |
|
// block here. For now, there doesn't appear a good workaround; just disable |
140 |
|
// assertions on that setup. |
141 |
|
#if defined(CVC5_ASSERTIONS) && !(defined(__clang__)) |
142 |
294323 |
if(d_te->isFinished()) { |
143 |
|
try { |
144 |
3147 |
**d_te; |
145 |
|
Assert(false) << "expected an NoMoreValuesException to be thrown"; |
146 |
3147 |
} catch(NoMoreValuesException&) { |
147 |
|
// ignore the exception, we're just asserting that it would be thrown |
148 |
|
// |
149 |
|
// This block can crash on clang 3.0 on Mac OS, perhaps related to |
150 |
|
// bug: http://llvm.org/bugs/show_bug.cgi?id=13359 |
151 |
|
// |
152 |
|
// Hence the #if !(defined(__APPLE__) && defined(__clang__)) above |
153 |
|
} |
154 |
|
} else { |
155 |
|
try { |
156 |
291176 |
**d_te; |
157 |
|
} catch(NoMoreValuesException&) { |
158 |
|
Assert(false) << "didn't expect a NoMoreValuesException to be thrown"; |
159 |
|
} |
160 |
|
} |
161 |
|
#endif /* CVC5_ASSERTIONS && !(APPLE || clang) */ |
162 |
294323 |
return d_te->isFinished(); |
163 |
|
} |
164 |
256522 |
Node operator*() |
165 |
|
{ |
166 |
|
// On Mac clang, there appears to be a code generation bug in an exception |
167 |
|
// block above (and perhaps here, too). For now, there doesn't appear a |
168 |
|
// good workaround; just disable assertions on that setup. |
169 |
|
#if defined(CVC5_ASSERTIONS) && !(defined(__APPLE__) && defined(__clang__)) |
170 |
|
try { |
171 |
513026 |
Node n = **d_te; |
172 |
256504 |
Assert(n.isConst()) << "Term " << n |
173 |
|
<< " from type enumerator is not constant"; |
174 |
256504 |
Assert(!isFinished()); |
175 |
513008 |
return n; |
176 |
36 |
} catch(NoMoreValuesException&) { |
177 |
18 |
Assert(isFinished()); |
178 |
18 |
throw; |
179 |
|
} |
180 |
|
#else /* CVC5_ASSERTIONS && !(APPLE || clang) */ |
181 |
|
return **d_te; |
182 |
|
#endif /* CVC5_ASSERTIONS && !(APPLE || clang) */ |
183 |
|
} |
184 |
35668 |
TypeEnumerator& operator++() |
185 |
|
{ |
186 |
35668 |
++*d_te; |
187 |
35668 |
return *this; |
188 |
|
} |
189 |
2040 |
TypeEnumerator operator++(int) |
190 |
|
{ |
191 |
2040 |
TypeEnumerator te = *this; |
192 |
2040 |
++*d_te; |
193 |
2040 |
return te; |
194 |
|
} |
195 |
|
|
196 |
2082 |
TypeNode getType() const { return d_te->getType(); } |
197 |
|
};/* class TypeEnumerator */ |
198 |
|
|
199 |
|
} // namespace theory |
200 |
|
} // namespace cvc5 |
201 |
|
|
202 |
|
#endif /* CVC5__THEORY__TYPE_ENUMERATOR_H */ |