1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Morgan Deters, Dejan Jovanovic, 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 |
|
* Reference-counted encapsulation of a pointer to node information. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
// circular dependency |
19 |
|
#include "expr/node_value.h" |
20 |
|
|
21 |
|
#ifndef CVC5__TYPE_NODE_H |
22 |
|
#define CVC5__TYPE_NODE_H |
23 |
|
|
24 |
|
#include <iostream> |
25 |
|
#include <string> |
26 |
|
#include <unordered_map> |
27 |
|
#include <vector> |
28 |
|
|
29 |
|
#include "base/check.h" |
30 |
|
#include "expr/kind.h" |
31 |
|
#include "expr/metakind.h" |
32 |
|
#include "util/cardinality.h" |
33 |
|
#include "util/cardinality_class.h" |
34 |
|
|
35 |
|
namespace cvc5 { |
36 |
|
|
37 |
|
class NodeManager; |
38 |
|
class DType; |
39 |
|
|
40 |
|
namespace expr { |
41 |
|
class NodeValue; |
42 |
|
} // namespace expr |
43 |
|
|
44 |
|
/** |
45 |
|
* Encapsulation of an NodeValue pointer for Types. The reference count is |
46 |
|
* maintained in the NodeValue. |
47 |
|
*/ |
48 |
|
class TypeNode { |
49 |
|
|
50 |
|
private: |
51 |
|
|
52 |
|
/** |
53 |
|
* The NodeValue has access to the private constructors, so that the |
54 |
|
* iterators can can create new types. |
55 |
|
*/ |
56 |
|
friend class expr::NodeValue; |
57 |
|
|
58 |
|
/** A convenient null-valued encapsulated pointer */ |
59 |
|
static TypeNode s_null; |
60 |
|
|
61 |
|
/** The referenced NodeValue */ |
62 |
|
expr::NodeValue* d_nv; |
63 |
|
|
64 |
|
/** |
65 |
|
* This constructor is reserved for use by the TypeNode package. |
66 |
|
*/ |
67 |
|
explicit TypeNode(const expr::NodeValue*); |
68 |
|
|
69 |
|
friend class NodeManager; |
70 |
|
|
71 |
|
friend class NodeBuilder; |
72 |
|
|
73 |
|
/** |
74 |
|
* Assigns the expression value and does reference counting. No |
75 |
|
* assumptions are made on the expression, and should only be used |
76 |
|
* if we know what we are doing. |
77 |
|
* |
78 |
|
* @param ev the expression value to assign |
79 |
|
*/ |
80 |
|
void assignNodeValue(expr::NodeValue* ev); |
81 |
|
|
82 |
|
/** |
83 |
|
* Cache-aware, recursive version of substitute() used by the public |
84 |
|
* member function with a similar signature. |
85 |
|
*/ |
86 |
|
TypeNode substitute(const TypeNode& type, |
87 |
|
const TypeNode& replacement, |
88 |
|
std::unordered_map<TypeNode, TypeNode>& cache) const; |
89 |
|
|
90 |
|
/** |
91 |
|
* Cache-aware, recursive version of substitute() used by the public |
92 |
|
* member function with a similar signature. |
93 |
|
*/ |
94 |
|
template <class Iterator1, class Iterator2> |
95 |
|
TypeNode substitute(Iterator1 typesBegin, |
96 |
|
Iterator1 typesEnd, |
97 |
|
Iterator2 replacementsBegin, |
98 |
|
Iterator2 replacementsEnd, |
99 |
|
std::unordered_map<TypeNode, TypeNode>& cache) const; |
100 |
|
|
101 |
|
public: |
102 |
|
/** Default constructor, makes a null expression. */ |
103 |
771008864 |
TypeNode() : d_nv(&expr::NodeValue::null()) { } |
104 |
|
|
105 |
|
/** Copy constructor */ |
106 |
|
TypeNode(const TypeNode& node); |
107 |
|
|
108 |
|
/** |
109 |
|
* Destructor. If ref_count is true it will decrement the reference count |
110 |
|
* and, if zero, collect the NodeValue. |
111 |
|
*/ |
112 |
|
~TypeNode(); |
113 |
|
|
114 |
|
/** |
115 |
|
* Assignment operator for nodes, copies the relevant information from node |
116 |
|
* to this node. |
117 |
|
* |
118 |
|
* @param typeNode the node to copy |
119 |
|
* @return reference to this node |
120 |
|
*/ |
121 |
|
TypeNode& operator=(const TypeNode& typeNode); |
122 |
|
|
123 |
|
/** |
124 |
|
* Return the null node. |
125 |
|
* |
126 |
|
* @return the null node |
127 |
|
*/ |
128 |
4217 |
static TypeNode null() { |
129 |
4217 |
return s_null; |
130 |
|
} |
131 |
|
|
132 |
|
/** |
133 |
|
* Substitution of TypeNodes. |
134 |
|
*/ |
135 |
|
inline TypeNode |
136 |
|
substitute(const TypeNode& type, const TypeNode& replacement) const; |
137 |
|
|
138 |
|
/** |
139 |
|
* Simultaneous substitution of TypeNodes. |
140 |
|
*/ |
141 |
|
template <class Iterator1, class Iterator2> |
142 |
|
inline TypeNode |
143 |
|
substitute(Iterator1 typesBegin, Iterator1 typesEnd, |
144 |
|
Iterator2 replacementsBegin, Iterator2 replacementsEnd) const; |
145 |
|
|
146 |
|
/** |
147 |
|
* Structural comparison operator for expressions. |
148 |
|
* |
149 |
|
* @param typeNode the type node to compare to |
150 |
|
* @return true if expressions are equal, false otherwise |
151 |
|
*/ |
152 |
35919687 |
bool operator==(const TypeNode& typeNode) const { |
153 |
35919687 |
return d_nv == typeNode.d_nv; |
154 |
|
} |
155 |
|
|
156 |
|
/** |
157 |
|
* Structural comparison operator for expressions. |
158 |
|
* |
159 |
|
* @param typeNode the type node to compare to |
160 |
|
* @return true if expressions are equal, false otherwise |
161 |
|
*/ |
162 |
7816890 |
bool operator!=(const TypeNode& typeNode) const { |
163 |
7816890 |
return !(*this == typeNode); |
164 |
|
} |
165 |
|
|
166 |
|
/** |
167 |
|
* We compare by expression ids so, keeping things deterministic and having |
168 |
|
* that subexpressions have to be smaller than the enclosing expressions. |
169 |
|
* |
170 |
|
* @param typeNode the node to compare to |
171 |
|
* @return true if this expression is lesser |
172 |
|
*/ |
173 |
52565909 |
inline bool operator<(const TypeNode& typeNode) const { |
174 |
52565909 |
return d_nv->d_id < typeNode.d_nv->d_id; |
175 |
|
} |
176 |
|
|
177 |
|
/** |
178 |
|
* We compare by expression ids so, keeping things deterministic and having |
179 |
|
* that subexpressions have to be smaller than the enclosing expressions. |
180 |
|
* |
181 |
|
* @param typeNode the node to compare to |
182 |
|
* @return true if this expression is lesser or equal |
183 |
|
*/ |
184 |
4 |
inline bool operator<=(const TypeNode& typeNode) const { |
185 |
4 |
return d_nv->d_id <= typeNode.d_nv->d_id; |
186 |
|
} |
187 |
|
|
188 |
|
/** |
189 |
|
* We compare by expression ids so, keeping things deterministic and having |
190 |
|
* that subexpressions have to be smaller than the enclosing expressions. |
191 |
|
* |
192 |
|
* @param typeNode the node to compare to |
193 |
|
* @return true if this expression is greater |
194 |
|
*/ |
195 |
6 |
inline bool operator>(const TypeNode& typeNode) const { |
196 |
6 |
return d_nv->d_id > typeNode.d_nv->d_id; |
197 |
|
} |
198 |
|
|
199 |
|
/** |
200 |
|
* We compare by expression ids so, keeping things deterministic and having |
201 |
|
* that subexpressions have to be smaller than the enclosing expressions. |
202 |
|
* |
203 |
|
* @param typeNode the node to compare to |
204 |
|
* @return true if this expression is greater or equal |
205 |
|
*/ |
206 |
6 |
inline bool operator>=(const TypeNode& typeNode) const { |
207 |
6 |
return d_nv->d_id >= typeNode.d_nv->d_id; |
208 |
|
} |
209 |
|
|
210 |
|
/** |
211 |
|
* Returns the i-th child of this node. |
212 |
|
* |
213 |
|
* @param i the index of the child |
214 |
|
* @return the node representing the i-th child |
215 |
|
*/ |
216 |
4331557 |
inline TypeNode operator[](int i) const { |
217 |
4331557 |
return TypeNode(d_nv->getChild(i)); |
218 |
|
} |
219 |
|
|
220 |
|
/** |
221 |
|
* PARAMETERIZED-metakinded types (the SORT_TYPE is one of these) |
222 |
|
* have an operator. "Little-p parameterized" types (like Array), |
223 |
|
* are OPERATORs, not PARAMETERIZEDs. |
224 |
|
*/ |
225 |
|
inline Node getOperator() const { |
226 |
|
Assert(getMetaKind() == kind::metakind::PARAMETERIZED); |
227 |
|
return Node(d_nv->getOperator()); |
228 |
|
} |
229 |
|
|
230 |
|
/** |
231 |
|
* Returns the unique id of this node |
232 |
|
* |
233 |
|
* @return the id |
234 |
|
*/ |
235 |
2986437 |
inline unsigned long getId() const { |
236 |
2986437 |
return d_nv->getId(); |
237 |
|
} |
238 |
|
|
239 |
|
/** |
240 |
|
* Returns the kind of this type node. |
241 |
|
* |
242 |
|
* @return the kind |
243 |
|
*/ |
244 |
462833071 |
inline Kind getKind() const { |
245 |
462833071 |
return Kind(d_nv->d_kind); |
246 |
|
} |
247 |
|
|
248 |
|
/** |
249 |
|
* Returns the metakind of this type node. |
250 |
|
* |
251 |
|
* @return the metakind |
252 |
|
*/ |
253 |
1996 |
inline kind::MetaKind getMetaKind() const { |
254 |
1996 |
return kind::metaKindOf(getKind()); |
255 |
|
} |
256 |
|
|
257 |
|
/** |
258 |
|
* Returns the number of children this node has. |
259 |
|
* |
260 |
|
* @return the number of children |
261 |
|
*/ |
262 |
|
inline size_t getNumChildren() const; |
263 |
|
|
264 |
|
/** |
265 |
|
* If this is a CONST_* TypeNode, extract the constant from it. |
266 |
|
*/ |
267 |
|
template <class T> |
268 |
|
inline const T& getConst() const; |
269 |
|
|
270 |
|
/** |
271 |
|
* Returns the value of the given attribute that this has been attached. |
272 |
|
* |
273 |
|
* @param attKind the kind of the attribute |
274 |
|
* @return the value of the attribute |
275 |
|
*/ |
276 |
|
template <class AttrKind> |
277 |
|
inline typename AttrKind::value_type |
278 |
|
getAttribute(const AttrKind& attKind) const; |
279 |
|
|
280 |
|
// Note that there are two, distinct hasAttribute() declarations for |
281 |
|
// a reason (rather than using a pointer-valued argument with a |
282 |
|
// default value): they permit more optimized code in the underlying |
283 |
|
// hasAttribute() implementations. |
284 |
|
|
285 |
|
/** |
286 |
|
* Returns true if this node has been associated an attribute of |
287 |
|
* given kind. Additionally, if a pointer to the value_kind is |
288 |
|
* give, and the attribute value has been set for this node, it will |
289 |
|
* be returned. |
290 |
|
* |
291 |
|
* @param attKind the kind of the attribute |
292 |
|
* @return true if this node has the requested attribute |
293 |
|
*/ |
294 |
|
template <class AttrKind> |
295 |
|
inline bool hasAttribute(const AttrKind& attKind) const; |
296 |
|
|
297 |
|
/** |
298 |
|
* Returns true if this node has been associated an attribute of given kind. |
299 |
|
* Additionaly, if a pointer to the value_kind is give, and the attribute |
300 |
|
* value has been set for this node, it will be returned. |
301 |
|
* |
302 |
|
* @param attKind the kind of the attribute |
303 |
|
* @param value where to store the value if it exists |
304 |
|
* @return true if this node has the requested attribute |
305 |
|
*/ |
306 |
|
template <class AttrKind> |
307 |
|
inline bool getAttribute(const AttrKind& attKind, |
308 |
|
typename AttrKind::value_type& value) const; |
309 |
|
|
310 |
|
/** |
311 |
|
* Sets the given attribute of this node to the given value. |
312 |
|
* |
313 |
|
* @param attKind the kind of the atribute |
314 |
|
* @param value the value to set the attribute to |
315 |
|
*/ |
316 |
|
template <class AttrKind> |
317 |
|
inline void setAttribute(const AttrKind& attKind, |
318 |
|
const typename AttrKind::value_type& value); |
319 |
|
|
320 |
|
/** Iterator allowing for scanning through the children. */ |
321 |
|
typedef expr::NodeValue::iterator<TypeNode> iterator; |
322 |
|
/** Constant iterator allowing for scanning through the children. */ |
323 |
|
typedef expr::NodeValue::iterator<TypeNode> const_iterator; |
324 |
|
|
325 |
|
/** |
326 |
|
* Returns the iterator pointing to the first child. |
327 |
|
* |
328 |
|
* @return the iterator |
329 |
|
*/ |
330 |
593452 |
inline iterator begin() { |
331 |
593452 |
return d_nv->begin<TypeNode>(); |
332 |
|
} |
333 |
|
|
334 |
|
/** |
335 |
|
* Returns the iterator pointing to the end of the children (one |
336 |
|
* beyond the last one. |
337 |
|
* |
338 |
|
* @return the end of the children iterator. |
339 |
|
*/ |
340 |
11148 |
inline iterator end() { |
341 |
11148 |
return d_nv->end<TypeNode>(); |
342 |
|
} |
343 |
|
|
344 |
|
/** |
345 |
|
* Returns the const_iterator pointing to the first child. |
346 |
|
* |
347 |
|
* @return the const_iterator |
348 |
|
*/ |
349 |
1996 |
inline const_iterator begin() const { |
350 |
1996 |
return d_nv->begin<TypeNode>(); |
351 |
|
} |
352 |
|
|
353 |
|
/** |
354 |
|
* Returns the const_iterator pointing to the end of the children |
355 |
|
* (one beyond the last one. |
356 |
|
* |
357 |
|
* @return the end of the children const_iterator. |
358 |
|
*/ |
359 |
1996 |
inline const_iterator end() const { |
360 |
1996 |
return d_nv->end<TypeNode>(); |
361 |
|
} |
362 |
|
|
363 |
|
/** |
364 |
|
* Converts this type into a string representation. |
365 |
|
* |
366 |
|
* @return the string representation of this type. |
367 |
|
*/ |
368 |
|
std::string toString() const; |
369 |
|
|
370 |
|
/** |
371 |
|
* Converts this node into a string representation and sends it to the |
372 |
|
* given stream |
373 |
|
* |
374 |
|
* @param out the stream to serialize this node to |
375 |
|
* @param language the language in which to output |
376 |
|
*/ |
377 |
19829 |
inline void toStream(std::ostream& out, OutputLanguage language = language::output::LANG_AUTO) const { |
378 |
19829 |
d_nv->toStream(out, -1, 0, language); |
379 |
19829 |
} |
380 |
|
|
381 |
|
/** |
382 |
|
* Very basic pretty printer for Node. |
383 |
|
* |
384 |
|
* @param out output stream to print to. |
385 |
|
* @param indent number of spaces to indent the formula by. |
386 |
|
*/ |
387 |
|
void printAst(std::ostream& out, int indent = 0) const; |
388 |
|
|
389 |
|
/** |
390 |
|
* Returns true if this type is a null type. |
391 |
|
* |
392 |
|
* @return true if null |
393 |
|
*/ |
394 |
26193306 |
bool isNull() const { |
395 |
26193306 |
return d_nv == &expr::NodeValue::null(); |
396 |
|
} |
397 |
|
|
398 |
|
/** |
399 |
|
* Returns the cardinality of this type. |
400 |
|
* |
401 |
|
* @return a finite or infinite cardinality |
402 |
|
*/ |
403 |
|
Cardinality getCardinality() const; |
404 |
|
/** |
405 |
|
* Get the cardinality class of this type node. The cardinality class |
406 |
|
* is static for each type node and does not depend on the state of the |
407 |
|
* solver. For details on cardinality classes, see util/cardinality_class.h |
408 |
|
* |
409 |
|
* @return the cardinality class |
410 |
|
*/ |
411 |
|
CardinalityClass getCardinalityClass(); |
412 |
|
|
413 |
|
/** is closed enumerable type |
414 |
|
* |
415 |
|
* This returns true if this type has an enumerator that produces constants |
416 |
|
* that are fully handled by cvc5's quantifier-free theory solvers. Examples |
417 |
|
* of types that are not closed enumerable are: |
418 |
|
* (1) uninterpreted sorts, |
419 |
|
* (2) arrays, |
420 |
|
* (3) codatatypes, |
421 |
|
* (4) functions, |
422 |
|
* (5) parametric sorts involving any of the above. |
423 |
|
*/ |
424 |
|
bool isClosedEnumerable(); |
425 |
|
|
426 |
|
/** |
427 |
|
* Is this a first-class type? |
428 |
|
* First-class types are types for which: |
429 |
|
* (1) we handle equalities between terms of that type, and |
430 |
|
* (2) they are allowed to be parameters of parametric types (e.g. index or element types of arrays). |
431 |
|
* |
432 |
|
* Examples of types that are not first-class include constructor types, |
433 |
|
* selector types, tester types, regular expressions and SExprs. |
434 |
|
*/ |
435 |
|
bool isFirstClass() const; |
436 |
|
|
437 |
|
/** |
438 |
|
* Returns whether this type is well-founded. |
439 |
|
* |
440 |
|
* @return true iff the type is well-founded |
441 |
|
*/ |
442 |
|
bool isWellFounded() const; |
443 |
|
|
444 |
|
/** |
445 |
|
* Construct and return a ground term of this type. If the type is |
446 |
|
* not well founded, this function throws an exception. |
447 |
|
* |
448 |
|
* @return a ground term of the type |
449 |
|
*/ |
450 |
|
Node mkGroundTerm() const; |
451 |
|
|
452 |
|
/** |
453 |
|
* Construct and return a ground value of this type. If the type is |
454 |
|
* not well founded, this function throws an exception. |
455 |
|
* |
456 |
|
* @return a ground value of the type |
457 |
|
*/ |
458 |
|
Node mkGroundValue() const; |
459 |
|
|
460 |
|
/** |
461 |
|
* Is this type a subtype of the given type? |
462 |
|
*/ |
463 |
|
bool isSubtypeOf(TypeNode t) const; |
464 |
|
|
465 |
|
/** |
466 |
|
* Is this type comparable to the given type (i.e., do they share |
467 |
|
* a common ancestor in the subtype tree)? |
468 |
|
*/ |
469 |
|
bool isComparableTo(TypeNode t) const; |
470 |
|
|
471 |
|
/** Is this the Boolean type? */ |
472 |
|
bool isBoolean() const; |
473 |
|
|
474 |
|
/** Is this the Integer type? */ |
475 |
|
bool isInteger() const; |
476 |
|
|
477 |
|
/** Is this the Real type? */ |
478 |
|
bool isReal() const; |
479 |
|
|
480 |
|
/** Is this the String type? */ |
481 |
|
bool isString() const; |
482 |
|
|
483 |
|
/** Is this a string-like type? (string or sequence) */ |
484 |
|
bool isStringLike() const; |
485 |
|
|
486 |
|
/** Is this the Rounding Mode type? */ |
487 |
|
bool isRoundingMode() const; |
488 |
|
|
489 |
|
/** Is this an array type? */ |
490 |
|
bool isArray() const; |
491 |
|
|
492 |
|
/** Is this a Set type? */ |
493 |
|
bool isSet() const; |
494 |
|
|
495 |
|
/** Is this a Bag type? */ |
496 |
|
bool isBag() const; |
497 |
|
|
498 |
|
/** Is this a Sequence type? */ |
499 |
|
bool isSequence() const; |
500 |
|
|
501 |
|
/** Get the index type (for array types) */ |
502 |
|
TypeNode getArrayIndexType() const; |
503 |
|
|
504 |
|
/** Get the element type (for array types) */ |
505 |
|
TypeNode getArrayConstituentType() const; |
506 |
|
|
507 |
|
/** Get the return type (for constructor types) */ |
508 |
|
TypeNode getConstructorRangeType() const; |
509 |
|
|
510 |
|
/** Get the domain type (for selector types) */ |
511 |
|
TypeNode getSelectorDomainType() const; |
512 |
|
|
513 |
|
/** Get the return type (for selector types) */ |
514 |
|
TypeNode getSelectorRangeType() const; |
515 |
|
|
516 |
|
/** Get the domain type (for tester types) */ |
517 |
|
TypeNode getTesterDomainType() const; |
518 |
|
|
519 |
|
/** Get the element type (for set types) */ |
520 |
|
TypeNode getSetElementType() const; |
521 |
|
|
522 |
|
/** Get the element type (for bag types) */ |
523 |
|
TypeNode getBagElementType() const; |
524 |
|
|
525 |
|
/** Get the element type (for sequence types) */ |
526 |
|
TypeNode getSequenceElementType() const; |
527 |
|
/** |
528 |
|
* Is this a function type? Function-like things (e.g. datatype |
529 |
|
* selectors) that aren't actually functions are NOT considered |
530 |
|
* functions, here. |
531 |
|
*/ |
532 |
|
bool isFunction() const; |
533 |
|
|
534 |
|
/** |
535 |
|
* Is this a function-LIKE type? Function-like things |
536 |
|
* (e.g. datatype selectors) that aren't actually functions ARE |
537 |
|
* considered functions, here. The main point is that this is used |
538 |
|
* to avoid anything higher-order: anything function-like cannot be |
539 |
|
* the argument or return value for anything else function-like. |
540 |
|
* |
541 |
|
* Arrays are explicitly *not* function-like for the purposes of |
542 |
|
* this test. However, functions still cannot contain anything |
543 |
|
* function-like. |
544 |
|
*/ |
545 |
|
bool isFunctionLike() const; |
546 |
|
|
547 |
|
/** |
548 |
|
* Get the argument types of a function, datatype constructor, |
549 |
|
* datatype selector, or datatype tester. |
550 |
|
*/ |
551 |
|
std::vector<TypeNode> getArgTypes() const; |
552 |
|
|
553 |
|
/** |
554 |
|
* Get the paramater types of a parameterized datatype. Fails an |
555 |
|
* assertion if this type is not a parametric datatype. |
556 |
|
*/ |
557 |
|
std::vector<TypeNode> getParamTypes() const; |
558 |
|
|
559 |
|
/** |
560 |
|
* Get the range type (i.e., the type of the result) of a function, |
561 |
|
* datatype constructor, datatype selector, or datatype tester. |
562 |
|
*/ |
563 |
|
TypeNode getRangeType() const; |
564 |
|
|
565 |
|
/** |
566 |
|
* Is this a predicate type? NOTE: all predicate types are also |
567 |
|
* function types (so datatype testers are NOT considered |
568 |
|
* "predicates" for the purpose of this function). |
569 |
|
*/ |
570 |
|
bool isPredicate() const; |
571 |
|
|
572 |
|
/** |
573 |
|
* Is this a predicate-LIKE type? Predicate-like things |
574 |
|
* (e.g. datatype testers) that aren't actually predicates ARE |
575 |
|
* considered predicates, here. |
576 |
|
* |
577 |
|
* Arrays are explicitly *not* predicate-like for the purposes of |
578 |
|
* this test. |
579 |
|
*/ |
580 |
|
bool isPredicateLike() const; |
581 |
|
|
582 |
|
/** Is this a tuple type? */ |
583 |
|
bool isTuple() const; |
584 |
|
|
585 |
|
/** Is this a record type? */ |
586 |
|
bool isRecord() const; |
587 |
|
|
588 |
|
/** Get the length of a tuple type */ |
589 |
|
size_t getTupleLength() const; |
590 |
|
|
591 |
|
/** Get the constituent types of a tuple type */ |
592 |
|
std::vector<TypeNode> getTupleTypes() const; |
593 |
|
|
594 |
|
/** Is this a regexp type */ |
595 |
|
bool isRegExp() const; |
596 |
|
|
597 |
|
/** Is this a floating-point type */ |
598 |
|
bool isFloatingPoint() const; |
599 |
|
|
600 |
|
/** Is this a floating-point type of with <code>exp</code> exponent bits |
601 |
|
and <code>sig</code> significand bits */ |
602 |
|
bool isFloatingPoint(unsigned exp, unsigned sig) const; |
603 |
|
|
604 |
|
/** Is this a bit-vector type */ |
605 |
|
bool isBitVector() const; |
606 |
|
|
607 |
|
/** Is this a bit-vector type of size <code>size</code> */ |
608 |
|
bool isBitVector(unsigned size) const; |
609 |
|
|
610 |
|
/** Is this a datatype type */ |
611 |
|
bool isDatatype() const; |
612 |
|
|
613 |
|
/** Is this a parameterized datatype type */ |
614 |
|
bool isParametricDatatype() const; |
615 |
|
|
616 |
|
/** Is this a codatatype type */ |
617 |
|
bool isCodatatype() const; |
618 |
|
|
619 |
|
/** Is this a fully instantiated datatype type */ |
620 |
|
bool isInstantiatedDatatype() const; |
621 |
|
|
622 |
|
/** Is this a sygus datatype type */ |
623 |
|
bool isSygusDatatype() const; |
624 |
|
|
625 |
|
/** |
626 |
|
* Get instantiated datatype type. The type on which this method is called |
627 |
|
* should be a parametric datatype whose parameter list is the same size as |
628 |
|
* argument params. This constructs the instantiated version of this |
629 |
|
* parametric datatype, e.g. passing (par (A) (List A)), { Int } ) to this |
630 |
|
* method returns (List Int). |
631 |
|
*/ |
632 |
|
TypeNode instantiateParametricDatatype( |
633 |
|
const std::vector<TypeNode>& params) const; |
634 |
|
|
635 |
|
/** Is this an instantiated datatype parameter */ |
636 |
|
bool isParameterInstantiatedDatatype(unsigned n) const; |
637 |
|
|
638 |
|
/** Is this a constructor type */ |
639 |
|
bool isConstructor() const; |
640 |
|
|
641 |
|
/** Is this a selector type */ |
642 |
|
bool isSelector() const; |
643 |
|
|
644 |
|
/** Is this a tester type */ |
645 |
|
bool isTester() const; |
646 |
|
|
647 |
|
/** Is this a datatype updater type */ |
648 |
|
bool isUpdater() const; |
649 |
|
|
650 |
|
/** Get the internal Datatype specification from a datatype type */ |
651 |
|
const DType& getDType() const; |
652 |
|
|
653 |
|
/** Get the exponent size of this floating-point type */ |
654 |
|
unsigned getFloatingPointExponentSize() const; |
655 |
|
|
656 |
|
/** Get the significand size of this floating-point type */ |
657 |
|
unsigned getFloatingPointSignificandSize() const; |
658 |
|
|
659 |
|
/** Get the size of this bit-vector type */ |
660 |
|
unsigned getBitVectorSize() const; |
661 |
|
|
662 |
|
/** Is this a sort kind */ |
663 |
|
bool isSort() const; |
664 |
|
|
665 |
|
/** Is this a sort constructor kind */ |
666 |
|
bool isSortConstructor() const; |
667 |
|
|
668 |
|
/** Get sort constructor arity */ |
669 |
|
uint64_t getSortConstructorArity() const; |
670 |
|
|
671 |
|
/** |
672 |
|
* Get name, for uninterpreted sorts and uninterpreted sort constructors. |
673 |
|
*/ |
674 |
|
std::string getName() const; |
675 |
|
|
676 |
|
/** |
677 |
|
* Instantiate a sort constructor type. The type on which this method is |
678 |
|
* called should be a sort constructor type whose parameter list is the |
679 |
|
* same size as argument params. This constructs the instantiated version of |
680 |
|
* this sort constructor. For example, this is a sort constructor, e.g. |
681 |
|
* declared via (declare-sort U 2), then calling this method with |
682 |
|
* { Int, Int } will generate the instantiated sort (U Int Int). |
683 |
|
*/ |
684 |
|
TypeNode instantiateSortConstructor( |
685 |
|
const std::vector<TypeNode>& params) const; |
686 |
|
|
687 |
|
/** Get the most general base type of the type */ |
688 |
|
TypeNode getBaseType() const; |
689 |
|
|
690 |
|
/** |
691 |
|
* Returns the leastUpperBound in the extended type lattice of the two types. |
692 |
|
* If this is \top, i.e. there is no inhabited type that contains both, |
693 |
|
* a TypeNode such that isNull() is true is returned. |
694 |
|
*/ |
695 |
|
static TypeNode leastCommonTypeNode(TypeNode t0, TypeNode t1); |
696 |
|
static TypeNode mostCommonTypeNode(TypeNode t0, TypeNode t1); |
697 |
|
|
698 |
|
/** get ensure type condition |
699 |
|
* Return value is a condition that implies that n has type tn. |
700 |
|
*/ |
701 |
|
static Node getEnsureTypeCondition( Node n, TypeNode tn ); |
702 |
|
private: |
703 |
|
static TypeNode commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast); |
704 |
|
|
705 |
|
/** |
706 |
|
* Indents the given stream a given amount of spaces. |
707 |
|
* |
708 |
|
* @param out the stream to indent |
709 |
|
* @param indent the number of spaces |
710 |
|
*/ |
711 |
|
static void indent(std::ostream& out, int indent) { |
712 |
|
for(int i = 0; i < indent; i++) { |
713 |
|
out << ' '; |
714 |
|
} |
715 |
|
} |
716 |
|
|
717 |
|
};/* class TypeNode */ |
718 |
|
|
719 |
|
/** |
720 |
|
* Serializes a given node to the given stream. |
721 |
|
* |
722 |
|
* @param out the output stream to use |
723 |
|
* @param n the node to output to the stream |
724 |
|
* @return the stream |
725 |
|
*/ |
726 |
19785 |
inline std::ostream& operator<<(std::ostream& out, const TypeNode& n) { |
727 |
19785 |
n.toStream(out, Node::setlanguage::getLanguage(out)); |
728 |
19785 |
return out; |
729 |
|
} |
730 |
|
|
731 |
|
} // namespace cvc5 |
732 |
|
|
733 |
|
namespace std { |
734 |
|
|
735 |
|
template <> |
736 |
|
struct hash<cvc5::TypeNode> |
737 |
|
{ |
738 |
|
size_t operator()(const cvc5::TypeNode& tn) const; |
739 |
|
}; |
740 |
|
|
741 |
|
} // namespace std |
742 |
|
|
743 |
|
#include "expr/node_manager.h" |
744 |
|
|
745 |
|
namespace cvc5 { |
746 |
|
|
747 |
|
inline TypeNode |
748 |
2 |
TypeNode::substitute(const TypeNode& type, |
749 |
|
const TypeNode& replacement) const { |
750 |
4 |
std::unordered_map<TypeNode, TypeNode> cache; |
751 |
4 |
return substitute(type, replacement, cache); |
752 |
|
} |
753 |
|
|
754 |
|
template <class Iterator1, class Iterator2> |
755 |
|
inline TypeNode |
756 |
15305 |
TypeNode::substitute(Iterator1 typesBegin, |
757 |
|
Iterator1 typesEnd, |
758 |
|
Iterator2 replacementsBegin, |
759 |
|
Iterator2 replacementsEnd) const { |
760 |
30610 |
std::unordered_map<TypeNode, TypeNode> cache; |
761 |
|
return substitute(typesBegin, typesEnd, |
762 |
30610 |
replacementsBegin, replacementsEnd, cache); |
763 |
|
} |
764 |
|
|
765 |
|
template <class Iterator1, class Iterator2> |
766 |
19757 |
TypeNode TypeNode::substitute( |
767 |
|
Iterator1 typesBegin, |
768 |
|
Iterator1 typesEnd, |
769 |
|
Iterator2 replacementsBegin, |
770 |
|
Iterator2 replacementsEnd, |
771 |
|
std::unordered_map<TypeNode, TypeNode>& cache) const |
772 |
|
{ |
773 |
|
// in cache? |
774 |
19757 |
std::unordered_map<TypeNode, TypeNode>::const_iterator i = cache.find(*this); |
775 |
19757 |
if(i != cache.end()) { |
776 |
1124 |
return (*i).second; |
777 |
|
} |
778 |
|
|
779 |
|
// otherwise compute |
780 |
18633 |
Assert(typesEnd - typesBegin == replacementsEnd - replacementsBegin) |
781 |
|
<< "Substitution iterator ranges must be equal size"; |
782 |
18633 |
Iterator1 j = find(typesBegin, typesEnd, *this); |
783 |
18633 |
if(j != typesEnd) { |
784 |
28256 |
TypeNode tn = *(replacementsBegin + (j - typesBegin)); |
785 |
14128 |
cache[*this] = tn; |
786 |
14128 |
return tn; |
787 |
4505 |
} else if(getNumChildren() == 0) { |
788 |
2511 |
cache[*this] = *this; |
789 |
2511 |
return *this; |
790 |
|
} else { |
791 |
3988 |
NodeBuilder nb(getKind()); |
792 |
1994 |
if(getMetaKind() == kind::metakind::PARAMETERIZED) { |
793 |
|
// push the operator |
794 |
|
nb << TypeNode(d_nv->d_children[0]); |
795 |
|
} |
796 |
6446 |
for (const TypeNode& tn : *this) |
797 |
|
{ |
798 |
4452 |
nb << tn.substitute( |
799 |
|
typesBegin, typesEnd, replacementsBegin, replacementsEnd, cache); |
800 |
|
} |
801 |
3988 |
TypeNode tn = nb.constructTypeNode(); |
802 |
1994 |
cache[*this] = tn; |
803 |
1994 |
return tn; |
804 |
|
} |
805 |
|
} |
806 |
|
|
807 |
5359003 |
inline size_t TypeNode::getNumChildren() const { |
808 |
5359003 |
return d_nv->getNumChildren(); |
809 |
|
} |
810 |
|
|
811 |
|
template <class T> |
812 |
382195168 |
inline const T& TypeNode::getConst() const { |
813 |
382195168 |
return d_nv->getConst<T>(); |
814 |
|
} |
815 |
|
|
816 |
40849863 |
inline TypeNode::TypeNode(const expr::NodeValue* ev) : |
817 |
40849863 |
d_nv(const_cast<expr::NodeValue*> (ev)) { |
818 |
40849863 |
Assert(d_nv != NULL) << "Expecting a non-NULL expression value!"; |
819 |
40849863 |
d_nv->inc(); |
820 |
40849863 |
} |
821 |
|
|
822 |
766099013 |
inline TypeNode::TypeNode(const TypeNode& typeNode) { |
823 |
766099013 |
Assert(typeNode.d_nv != NULL) << "Expecting a non-NULL expression value!"; |
824 |
766099013 |
d_nv = typeNode.d_nv; |
825 |
766099013 |
d_nv->inc(); |
826 |
766099013 |
} |
827 |
|
|
828 |
3155914360 |
inline TypeNode::~TypeNode() { |
829 |
1577957180 |
Assert(d_nv != NULL) << "Expecting a non-NULL expression value!"; |
830 |
1577957180 |
d_nv->dec(); |
831 |
1577957180 |
} |
832 |
|
|
833 |
|
inline void TypeNode::assignNodeValue(expr::NodeValue* ev) { |
834 |
|
d_nv = ev; |
835 |
|
d_nv->inc(); |
836 |
|
} |
837 |
|
|
838 |
730972497 |
inline TypeNode& TypeNode::operator=(const TypeNode& typeNode) { |
839 |
730972497 |
Assert(d_nv != NULL) << "Expecting a non-NULL expression value!"; |
840 |
730972497 |
Assert(typeNode.d_nv != NULL) |
841 |
|
<< "Expecting a non-NULL expression value on RHS!"; |
842 |
730972497 |
if(__builtin_expect( ( d_nv != typeNode.d_nv ), true )) { |
843 |
730638798 |
d_nv->dec(); |
844 |
730638798 |
d_nv = typeNode.d_nv; |
845 |
730638798 |
d_nv->inc(); |
846 |
|
} |
847 |
730972497 |
return *this; |
848 |
|
} |
849 |
|
|
850 |
|
template <class AttrKind> |
851 |
6964244 |
inline typename AttrKind::value_type TypeNode:: |
852 |
|
getAttribute(const AttrKind&) const { |
853 |
6964244 |
Assert(NodeManager::currentNM() != NULL) |
854 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
855 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
856 |
6964244 |
return NodeManager::currentNM()->getAttribute(d_nv, AttrKind()); |
857 |
|
} |
858 |
|
|
859 |
|
template <class AttrKind> |
860 |
7588574 |
inline bool TypeNode:: |
861 |
|
hasAttribute(const AttrKind&) const { |
862 |
7588574 |
Assert(NodeManager::currentNM() != NULL) |
863 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
864 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
865 |
7588574 |
return NodeManager::currentNM()->hasAttribute(d_nv, AttrKind()); |
866 |
|
} |
867 |
|
|
868 |
|
template <class AttrKind> |
869 |
|
inline bool TypeNode::getAttribute(const AttrKind&, typename AttrKind::value_type& ret) const { |
870 |
|
Assert(NodeManager::currentNM() != NULL) |
871 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
872 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
873 |
|
return NodeManager::currentNM()->getAttribute(d_nv, AttrKind(), ret); |
874 |
|
} |
875 |
|
|
876 |
|
template <class AttrKind> |
877 |
24504 |
inline void TypeNode:: |
878 |
|
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) { |
879 |
24504 |
Assert(NodeManager::currentNM() != NULL) |
880 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
881 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
882 |
24504 |
NodeManager::currentNM()->setAttribute(d_nv, AttrKind(), value); |
883 |
24504 |
} |
884 |
|
|
885 |
|
inline void TypeNode::printAst(std::ostream& out, int indent) const { |
886 |
|
d_nv->printAst(out, indent); |
887 |
|
} |
888 |
|
|
889 |
99308245 |
inline bool TypeNode::isBoolean() const { |
890 |
|
return |
891 |
99308245 |
( getKind() == kind::TYPE_CONSTANT && getConst<TypeConstant>() == BOOLEAN_TYPE ); |
892 |
|
} |
893 |
|
|
894 |
229748136 |
inline bool TypeNode::isInteger() const { |
895 |
|
return |
896 |
229748136 |
( getKind() == kind::TYPE_CONSTANT && getConst<TypeConstant>() == INTEGER_TYPE ); |
897 |
|
} |
898 |
|
|
899 |
11051026 |
inline bool TypeNode::isReal() const { |
900 |
|
return |
901 |
19801465 |
( getKind() == kind::TYPE_CONSTANT && getConst<TypeConstant>() == REAL_TYPE ) || |
902 |
19801465 |
isInteger(); |
903 |
|
} |
904 |
|
|
905 |
4024675 |
inline bool TypeNode::isString() const { |
906 |
7986803 |
return getKind() == kind::TYPE_CONSTANT && |
907 |
7986803 |
getConst<TypeConstant>() == STRING_TYPE; |
908 |
|
} |
909 |
|
|
910 |
|
/** Is this a regexp type */ |
911 |
1180768 |
inline bool TypeNode::isRegExp() const { |
912 |
2352558 |
return getKind() == kind::TYPE_CONSTANT && |
913 |
2352558 |
getConst<TypeConstant>() == REGEXP_TYPE; |
914 |
|
} |
915 |
|
|
916 |
32086 |
inline bool TypeNode::isRoundingMode() const { |
917 |
40233 |
return getKind() == kind::TYPE_CONSTANT && |
918 |
40233 |
getConst<TypeConstant>() == ROUNDINGMODE_TYPE; |
919 |
|
} |
920 |
|
|
921 |
1431178 |
inline bool TypeNode::isArray() const { |
922 |
1431178 |
return getKind() == kind::ARRAY_TYPE; |
923 |
|
} |
924 |
|
|
925 |
34435 |
inline TypeNode TypeNode::getArrayIndexType() const { |
926 |
34435 |
Assert(isArray()); |
927 |
34435 |
return (*this)[0]; |
928 |
|
} |
929 |
|
|
930 |
42372 |
inline TypeNode TypeNode::getArrayConstituentType() const { |
931 |
42372 |
Assert(isArray()); |
932 |
42372 |
return (*this)[1]; |
933 |
|
} |
934 |
|
|
935 |
243953 |
inline TypeNode TypeNode::getConstructorRangeType() const { |
936 |
243953 |
Assert(isConstructor()); |
937 |
243953 |
return (*this)[getNumChildren()-1]; |
938 |
|
} |
939 |
|
|
940 |
274878 |
inline TypeNode TypeNode::getSelectorDomainType() const |
941 |
|
{ |
942 |
274878 |
Assert(isSelector()); |
943 |
274878 |
return (*this)[0]; |
944 |
|
} |
945 |
|
|
946 |
752262 |
inline TypeNode TypeNode::getSelectorRangeType() const |
947 |
|
{ |
948 |
752262 |
Assert(isSelector()); |
949 |
752262 |
return (*this)[1]; |
950 |
|
} |
951 |
|
|
952 |
1360913 |
inline bool TypeNode::isSet() const { |
953 |
1360913 |
return getKind() == kind::SET_TYPE; |
954 |
|
} |
955 |
|
|
956 |
754060 |
inline bool TypeNode::isSequence() const |
957 |
|
{ |
958 |
754060 |
return getKind() == kind::SEQUENCE_TYPE; |
959 |
|
} |
960 |
|
|
961 |
702278 |
inline TypeNode TypeNode::getSetElementType() const { |
962 |
702278 |
Assert(isSet()); |
963 |
702278 |
return (*this)[0]; |
964 |
|
} |
965 |
|
|
966 |
7790079 |
inline bool TypeNode::isFunction() const { |
967 |
7790079 |
return getKind() == kind::FUNCTION_TYPE; |
968 |
|
} |
969 |
|
|
970 |
40022 |
inline bool TypeNode::isFunctionLike() const { |
971 |
|
return |
972 |
79966 |
getKind() == kind::FUNCTION_TYPE || |
973 |
79888 |
getKind() == kind::CONSTRUCTOR_TYPE || |
974 |
119876 |
getKind() == kind::SELECTOR_TYPE || |
975 |
79932 |
getKind() == kind::TESTER_TYPE; |
976 |
|
} |
977 |
|
|
978 |
92975 |
inline bool TypeNode::isPredicate() const { |
979 |
92975 |
return isFunction() && getRangeType().isBoolean(); |
980 |
|
} |
981 |
|
|
982 |
|
inline bool TypeNode::isPredicateLike() const { |
983 |
|
return isFunctionLike() && getRangeType().isBoolean(); |
984 |
|
} |
985 |
|
|
986 |
618149 |
inline TypeNode TypeNode::getRangeType() const { |
987 |
618149 |
if(isTester()) { |
988 |
|
return NodeManager::currentNM()->booleanType(); |
989 |
|
} |
990 |
618149 |
Assert(isFunction() || isConstructor() || isSelector()) |
991 |
|
<< "Cannot get range type of " << *this; |
992 |
618149 |
return (*this)[getNumChildren() - 1]; |
993 |
|
} |
994 |
|
|
995 |
|
/** Is this a floating-point type of with <code>exp</code> exponent bits |
996 |
|
and <code>sig</code> significand bits */ |
997 |
|
inline bool TypeNode::isFloatingPoint(unsigned exp, unsigned sig) const { |
998 |
|
return (getKind() == kind::FLOATINGPOINT_TYPE |
999 |
|
&& getConst<FloatingPointSize>().exponentWidth() == exp |
1000 |
|
&& getConst<FloatingPointSize>().significandWidth() == sig); |
1001 |
|
} |
1002 |
|
|
1003 |
|
/** Is this a bit-vector type of size <code>size</code> */ |
1004 |
1804 |
inline bool TypeNode::isBitVector(unsigned size) const { |
1005 |
|
return |
1006 |
1804 |
( getKind() == kind::BITVECTOR_TYPE && getConst<BitVectorSize>() == size ); |
1007 |
|
} |
1008 |
|
|
1009 |
|
/** Get the exponent size of this floating-point type */ |
1010 |
175 |
inline unsigned TypeNode::getFloatingPointExponentSize() const { |
1011 |
175 |
Assert(isFloatingPoint()); |
1012 |
175 |
return getConst<FloatingPointSize>().exponentWidth(); |
1013 |
|
} |
1014 |
|
|
1015 |
|
/** Get the significand size of this floating-point type */ |
1016 |
175 |
inline unsigned TypeNode::getFloatingPointSignificandSize() const { |
1017 |
175 |
Assert(isFloatingPoint()); |
1018 |
175 |
return getConst<FloatingPointSize>().significandWidth(); |
1019 |
|
} |
1020 |
|
|
1021 |
|
/** Get the size of this bit-vector type */ |
1022 |
5787449 |
inline unsigned TypeNode::getBitVectorSize() const { |
1023 |
5787449 |
Assert(isBitVector()); |
1024 |
5787449 |
return getConst<BitVectorSize>(); |
1025 |
|
} |
1026 |
|
|
1027 |
|
#ifdef CVC5_DEBUG |
1028 |
|
/** |
1029 |
|
* Pretty printer for use within gdb. This is not intended to be used |
1030 |
|
* outside of gdb. This writes to the Warning() stream and immediately |
1031 |
|
* flushes the stream. |
1032 |
|
* |
1033 |
|
* Note that this function cannot be a template, since the compiler |
1034 |
|
* won't instantiate it. Even if we explicitly instantiate. (Odd?) |
1035 |
|
* So we implement twice. We mark as __attribute__((used)) so that |
1036 |
|
* GCC emits code for it even though static analysis indicates it's |
1037 |
|
* never called. |
1038 |
|
* |
1039 |
|
* Tim's Note: I moved this into the node.h file because this allows gdb |
1040 |
|
* to find the symbol, and use it, which is the first standard this code needs |
1041 |
|
* to meet. A cleaner solution is welcomed. |
1042 |
|
*/ |
1043 |
|
static void __attribute__((used)) debugPrintTypeNode(const TypeNode& n) { |
1044 |
|
Warning() << Node::setdepth(-1) |
1045 |
|
<< Node::dag(true) |
1046 |
|
<< Node::setlanguage(language::output::LANG_AST) |
1047 |
|
<< n << std::endl; |
1048 |
|
Warning().flush(); |
1049 |
|
} |
1050 |
|
static void __attribute__((used)) debugPrintTypeNodeNoDag(const TypeNode& n) { |
1051 |
|
Warning() << Node::setdepth(-1) |
1052 |
|
<< Node::dag(false) |
1053 |
|
<< Node::setlanguage(language::output::LANG_AST) |
1054 |
|
<< n << std::endl; |
1055 |
|
Warning().flush(); |
1056 |
|
} |
1057 |
|
static void __attribute__((used)) debugPrintRawTypeNode(const TypeNode& n) { |
1058 |
|
n.printAst(Warning(), 0); |
1059 |
|
Warning().flush(); |
1060 |
|
} |
1061 |
|
#endif /* CVC5_DEBUG */ |
1062 |
|
|
1063 |
|
} // namespace cvc5 |
1064 |
|
|
1065 |
|
#endif /* CVC5__NODE_H */ |