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_class.h" |
33 |
|
|
34 |
|
namespace cvc5 { |
35 |
|
|
36 |
|
class NodeManager; |
37 |
|
class Cardinality; |
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 |
850645622 |
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 |
7265 |
static TypeNode null() { |
129 |
7265 |
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 |
36750223 |
bool operator==(const TypeNode& typeNode) const { |
153 |
36750223 |
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 |
8445344 |
bool operator!=(const TypeNode& typeNode) const { |
163 |
8445344 |
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 |
51396569 |
inline bool operator<(const TypeNode& typeNode) const { |
174 |
51396569 |
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 |
4344519 |
inline TypeNode operator[](int i) const { |
217 |
4344519 |
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 |
2916654 |
inline unsigned long getId() const { |
236 |
2916654 |
return d_nv->getId(); |
237 |
|
} |
238 |
|
|
239 |
|
/** |
240 |
|
* Returns the kind of this type node. |
241 |
|
* |
242 |
|
* @return the kind |
243 |
|
*/ |
244 |
536671239 |
inline Kind getKind() const { |
245 |
536671239 |
return Kind(d_nv->d_kind); |
246 |
|
} |
247 |
|
|
248 |
|
/** |
249 |
|
* Returns the metakind of this type node. |
250 |
|
* |
251 |
|
* @return the metakind |
252 |
|
*/ |
253 |
5208 |
inline kind::MetaKind getMetaKind() const { |
254 |
5208 |
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 |
593693 |
inline iterator begin() { |
331 |
593693 |
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 |
10831 |
inline iterator end() { |
341 |
10831 |
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 |
5208 |
inline const_iterator begin() const { |
350 |
5208 |
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 |
5208 |
inline const_iterator end() const { |
360 |
5208 |
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 |
19174 |
inline void toStream(std::ostream& out, |
378 |
|
Language language = Language::LANG_AUTO) const |
379 |
|
{ |
380 |
19174 |
d_nv->toStream(out, -1, 0, language); |
381 |
19174 |
} |
382 |
|
|
383 |
|
/** |
384 |
|
* Very basic pretty printer for Node. |
385 |
|
* |
386 |
|
* @param out output stream to print to. |
387 |
|
* @param indent number of spaces to indent the formula by. |
388 |
|
*/ |
389 |
|
void printAst(std::ostream& out, int indent = 0) const; |
390 |
|
|
391 |
|
/** |
392 |
|
* Returns true if this type is a null type. |
393 |
|
* |
394 |
|
* @return true if null |
395 |
|
*/ |
396 |
27887456 |
bool isNull() const { |
397 |
27887456 |
return d_nv == &expr::NodeValue::null(); |
398 |
|
} |
399 |
|
|
400 |
|
/** |
401 |
|
* Returns the cardinality of this type. |
402 |
|
* |
403 |
|
* @return a finite or infinite cardinality |
404 |
|
*/ |
405 |
|
Cardinality getCardinality() const; |
406 |
|
/** |
407 |
|
* Get the cardinality class of this type node. The cardinality class |
408 |
|
* is static for each type node and does not depend on the state of the |
409 |
|
* solver. For details on cardinality classes, see util/cardinality_class.h |
410 |
|
* |
411 |
|
* @return the cardinality class |
412 |
|
*/ |
413 |
|
CardinalityClass getCardinalityClass(); |
414 |
|
|
415 |
|
/** is closed enumerable type |
416 |
|
* |
417 |
|
* This returns true if this type has an enumerator that produces constants |
418 |
|
* that are fully handled by cvc5's quantifier-free theory solvers. Examples |
419 |
|
* of types that are not closed enumerable are: |
420 |
|
* (1) uninterpreted sorts, |
421 |
|
* (2) arrays, |
422 |
|
* (3) codatatypes, |
423 |
|
* (4) functions, |
424 |
|
* (5) parametric sorts involving any of the above. |
425 |
|
*/ |
426 |
|
bool isClosedEnumerable(); |
427 |
|
|
428 |
|
/** |
429 |
|
* Is this a first-class type? |
430 |
|
* First-class types are types for which: |
431 |
|
* (1) we handle equalities between terms of that type, and |
432 |
|
* (2) they are allowed to be parameters of parametric types (e.g. index or element types of arrays). |
433 |
|
* |
434 |
|
* Examples of types that are not first-class include constructor types, |
435 |
|
* selector types, tester types, regular expressions and SExprs. |
436 |
|
*/ |
437 |
|
bool isFirstClass() const; |
438 |
|
|
439 |
|
/** |
440 |
|
* Returns whether this type is well-founded. |
441 |
|
* |
442 |
|
* @return true iff the type is well-founded |
443 |
|
*/ |
444 |
|
bool isWellFounded() const; |
445 |
|
|
446 |
|
/** |
447 |
|
* Construct and return a ground term of this type. If the type is |
448 |
|
* not well founded, this function throws an exception. |
449 |
|
* |
450 |
|
* @return a ground term of the type |
451 |
|
*/ |
452 |
|
Node mkGroundTerm() const; |
453 |
|
|
454 |
|
/** |
455 |
|
* Construct and return a ground value of this type. If the type is |
456 |
|
* not well founded, this function throws an exception. |
457 |
|
* |
458 |
|
* @return a ground value of the type |
459 |
|
*/ |
460 |
|
Node mkGroundValue() const; |
461 |
|
|
462 |
|
/** |
463 |
|
* Is this type a subtype of the given type? |
464 |
|
*/ |
465 |
|
bool isSubtypeOf(TypeNode t) const; |
466 |
|
|
467 |
|
/** |
468 |
|
* Is this type comparable to the given type (i.e., do they share |
469 |
|
* a common ancestor in the subtype tree)? |
470 |
|
*/ |
471 |
|
bool isComparableTo(TypeNode t) const; |
472 |
|
|
473 |
|
/** Is this the Boolean type? */ |
474 |
|
bool isBoolean() const; |
475 |
|
|
476 |
|
/** Is this the Integer type? */ |
477 |
|
bool isInteger() const; |
478 |
|
|
479 |
|
/** Is this the Real type? */ |
480 |
|
bool isReal() const; |
481 |
|
|
482 |
|
/** Is this the String type? */ |
483 |
|
bool isString() const; |
484 |
|
|
485 |
|
/** Is this a string-like type? (string or sequence) */ |
486 |
|
bool isStringLike() const; |
487 |
|
|
488 |
|
/** Is this the Rounding Mode type? */ |
489 |
|
bool isRoundingMode() const; |
490 |
|
|
491 |
|
/** Is this an array type? */ |
492 |
|
bool isArray() const; |
493 |
|
|
494 |
|
/** Is this a Set type? */ |
495 |
|
bool isSet() const; |
496 |
|
|
497 |
|
/** Is this a Bag type? */ |
498 |
|
bool isBag() const; |
499 |
|
|
500 |
|
/** Is this a Sequence type? */ |
501 |
|
bool isSequence() const; |
502 |
|
|
503 |
|
/** Get the index type (for array types) */ |
504 |
|
TypeNode getArrayIndexType() const; |
505 |
|
|
506 |
|
/** Get the element type (for array types) */ |
507 |
|
TypeNode getArrayConstituentType() const; |
508 |
|
|
509 |
|
/** Get the return type (for constructor types) */ |
510 |
|
TypeNode getConstructorRangeType() const; |
511 |
|
|
512 |
|
/** Get the domain type (for selector types) */ |
513 |
|
TypeNode getSelectorDomainType() const; |
514 |
|
|
515 |
|
/** Get the return type (for selector types) */ |
516 |
|
TypeNode getSelectorRangeType() const; |
517 |
|
|
518 |
|
/** Get the domain type (for tester types) */ |
519 |
|
TypeNode getTesterDomainType() const; |
520 |
|
|
521 |
|
/** Get the element type (for set types) */ |
522 |
|
TypeNode getSetElementType() const; |
523 |
|
|
524 |
|
/** Get the element type (for bag types) */ |
525 |
|
TypeNode getBagElementType() const; |
526 |
|
|
527 |
|
/** Get the element type (for sequence types) */ |
528 |
|
TypeNode getSequenceElementType() const; |
529 |
|
/** |
530 |
|
* Is this a function type? Function-like things (e.g. datatype |
531 |
|
* selectors) that aren't actually functions are NOT considered |
532 |
|
* functions, here. |
533 |
|
*/ |
534 |
|
bool isFunction() const; |
535 |
|
|
536 |
|
/** |
537 |
|
* Is this a function-LIKE type? Function-like things |
538 |
|
* (e.g. datatype selectors) that aren't actually functions ARE |
539 |
|
* considered functions, here. The main point is that this is used |
540 |
|
* to avoid anything higher-order: anything function-like cannot be |
541 |
|
* the argument or return value for anything else function-like. |
542 |
|
* |
543 |
|
* Arrays are explicitly *not* function-like for the purposes of |
544 |
|
* this test. However, functions still cannot contain anything |
545 |
|
* function-like. |
546 |
|
*/ |
547 |
|
bool isFunctionLike() const; |
548 |
|
|
549 |
|
/** |
550 |
|
* Get the argument types of a function, datatype constructor, |
551 |
|
* datatype selector, or datatype tester. |
552 |
|
*/ |
553 |
|
std::vector<TypeNode> getArgTypes() const; |
554 |
|
|
555 |
|
/** |
556 |
|
* Get the paramater types of a parameterized datatype. Fails an |
557 |
|
* assertion if this type is not a parametric datatype. |
558 |
|
*/ |
559 |
|
std::vector<TypeNode> getParamTypes() const; |
560 |
|
|
561 |
|
/** |
562 |
|
* Get the range type (i.e., the type of the result) of a function, |
563 |
|
* datatype constructor, datatype selector, or datatype tester. |
564 |
|
*/ |
565 |
|
TypeNode getRangeType() const; |
566 |
|
|
567 |
|
/** |
568 |
|
* Is this a predicate type? NOTE: all predicate types are also |
569 |
|
* function types (so datatype testers are NOT considered |
570 |
|
* "predicates" for the purpose of this function). |
571 |
|
*/ |
572 |
|
bool isPredicate() const; |
573 |
|
|
574 |
|
/** |
575 |
|
* Is this a predicate-LIKE type? Predicate-like things |
576 |
|
* (e.g. datatype testers) that aren't actually predicates ARE |
577 |
|
* considered predicates, here. |
578 |
|
* |
579 |
|
* Arrays are explicitly *not* predicate-like for the purposes of |
580 |
|
* this test. |
581 |
|
*/ |
582 |
|
bool isPredicateLike() const; |
583 |
|
|
584 |
|
/** Is this a tuple type? */ |
585 |
|
bool isTuple() const; |
586 |
|
|
587 |
|
/** Is this a record type? */ |
588 |
|
bool isRecord() const; |
589 |
|
|
590 |
|
/** Get the length of a tuple type */ |
591 |
|
size_t getTupleLength() const; |
592 |
|
|
593 |
|
/** Get the constituent types of a tuple type */ |
594 |
|
std::vector<TypeNode> getTupleTypes() const; |
595 |
|
|
596 |
|
/** Is this a regexp type */ |
597 |
|
bool isRegExp() const; |
598 |
|
|
599 |
|
/** Is this a floating-point type */ |
600 |
|
bool isFloatingPoint() const; |
601 |
|
|
602 |
|
/** Is this a floating-point type of with <code>exp</code> exponent bits |
603 |
|
and <code>sig</code> significand bits */ |
604 |
|
bool isFloatingPoint(unsigned exp, unsigned sig) const; |
605 |
|
|
606 |
|
/** Is this a bit-vector type */ |
607 |
|
bool isBitVector() const; |
608 |
|
|
609 |
|
/** Is this a bit-vector type of size <code>size</code> */ |
610 |
|
bool isBitVector(unsigned size) const; |
611 |
|
|
612 |
|
/** Is this a datatype type */ |
613 |
|
bool isDatatype() const; |
614 |
|
|
615 |
|
/** Is this a parameterized datatype type */ |
616 |
|
bool isParametricDatatype() const; |
617 |
|
|
618 |
|
/** Is this a codatatype type */ |
619 |
|
bool isCodatatype() const; |
620 |
|
|
621 |
|
/** Is this a fully instantiated datatype type */ |
622 |
|
bool isInstantiatedDatatype() const; |
623 |
|
|
624 |
|
/** Is this a sygus datatype type */ |
625 |
|
bool isSygusDatatype() const; |
626 |
|
|
627 |
|
/** |
628 |
|
* Get instantiated datatype type. The type on which this method is called |
629 |
|
* should be a parametric datatype whose parameter list is the same size as |
630 |
|
* argument params. This constructs the instantiated version of this |
631 |
|
* parametric datatype, e.g. passing (par (A) (List A)), { Int } ) to this |
632 |
|
* method returns (List Int). |
633 |
|
*/ |
634 |
|
TypeNode instantiateParametricDatatype( |
635 |
|
const std::vector<TypeNode>& params) const; |
636 |
|
|
637 |
|
/** Is this an instantiated datatype parameter */ |
638 |
|
bool isParameterInstantiatedDatatype(unsigned n) const; |
639 |
|
|
640 |
|
/** Is this a constructor type */ |
641 |
|
bool isConstructor() const; |
642 |
|
|
643 |
|
/** Is this a selector type */ |
644 |
|
bool isSelector() const; |
645 |
|
|
646 |
|
/** Is this a tester type */ |
647 |
|
bool isTester() const; |
648 |
|
|
649 |
|
/** Is this a datatype updater type */ |
650 |
|
bool isUpdater() const; |
651 |
|
|
652 |
|
/** Get the internal Datatype specification from a datatype type */ |
653 |
|
const DType& getDType() const; |
654 |
|
|
655 |
|
/** Get the exponent size of this floating-point type */ |
656 |
|
unsigned getFloatingPointExponentSize() const; |
657 |
|
|
658 |
|
/** Get the significand size of this floating-point type */ |
659 |
|
unsigned getFloatingPointSignificandSize() const; |
660 |
|
|
661 |
|
/** Get the size of this bit-vector type */ |
662 |
|
uint32_t getBitVectorSize() const; |
663 |
|
|
664 |
|
/** Is this a sort kind */ |
665 |
|
bool isSort() const; |
666 |
|
|
667 |
|
/** Is this a sort constructor kind */ |
668 |
|
bool isSortConstructor() const; |
669 |
|
|
670 |
|
/** Get sort constructor arity */ |
671 |
|
uint64_t getSortConstructorArity() const; |
672 |
|
|
673 |
|
/** |
674 |
|
* Get name, for uninterpreted sorts and uninterpreted sort constructors. |
675 |
|
*/ |
676 |
|
std::string getName() const; |
677 |
|
|
678 |
|
/** |
679 |
|
* Instantiate a sort constructor type. The type on which this method is |
680 |
|
* called should be a sort constructor type whose parameter list is the |
681 |
|
* same size as argument params. This constructs the instantiated version of |
682 |
|
* this sort constructor. For example, this is a sort constructor, e.g. |
683 |
|
* declared via (declare-sort U 2), then calling this method with |
684 |
|
* { Int, Int } will generate the instantiated sort (U Int Int). |
685 |
|
*/ |
686 |
|
TypeNode instantiateSortConstructor( |
687 |
|
const std::vector<TypeNode>& params) const; |
688 |
|
|
689 |
|
/** Get the most general base type of the type */ |
690 |
|
TypeNode getBaseType() const; |
691 |
|
|
692 |
|
/** |
693 |
|
* Returns the leastUpperBound in the extended type lattice of the two types. |
694 |
|
* If this is \top, i.e. there is no inhabited type that contains both, |
695 |
|
* a TypeNode such that isNull() is true is returned. |
696 |
|
*/ |
697 |
|
static TypeNode leastCommonTypeNode(TypeNode t0, TypeNode t1); |
698 |
|
static TypeNode mostCommonTypeNode(TypeNode t0, TypeNode t1); |
699 |
|
|
700 |
|
/** get ensure type condition |
701 |
|
* Return value is a condition that implies that n has type tn. |
702 |
|
*/ |
703 |
|
static Node getEnsureTypeCondition( Node n, TypeNode tn ); |
704 |
|
private: |
705 |
|
static TypeNode commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast); |
706 |
|
|
707 |
|
/** |
708 |
|
* Indents the given stream a given amount of spaces. |
709 |
|
* |
710 |
|
* @param out the stream to indent |
711 |
|
* @param indent the number of spaces |
712 |
|
*/ |
713 |
|
static void indent(std::ostream& out, int indent) { |
714 |
|
for(int i = 0; i < indent; i++) { |
715 |
|
out << ' '; |
716 |
|
} |
717 |
|
} |
718 |
|
|
719 |
|
};/* class TypeNode */ |
720 |
|
|
721 |
|
/** |
722 |
|
* Serializes a given node to the given stream. |
723 |
|
* |
724 |
|
* @param out the output stream to use |
725 |
|
* @param n the node to output to the stream |
726 |
|
* @return the stream |
727 |
|
*/ |
728 |
19130 |
inline std::ostream& operator<<(std::ostream& out, const TypeNode& n) { |
729 |
19130 |
n.toStream(out, Node::setlanguage::getLanguage(out)); |
730 |
19130 |
return out; |
731 |
|
} |
732 |
|
|
733 |
|
} // namespace cvc5 |
734 |
|
|
735 |
|
namespace std { |
736 |
|
|
737 |
|
template <> |
738 |
|
struct hash<cvc5::TypeNode> |
739 |
|
{ |
740 |
|
size_t operator()(const cvc5::TypeNode& tn) const; |
741 |
|
}; |
742 |
|
|
743 |
|
} // namespace std |
744 |
|
|
745 |
|
#include "expr/node_manager.h" |
746 |
|
|
747 |
|
namespace cvc5 { |
748 |
|
|
749 |
|
inline TypeNode |
750 |
2 |
TypeNode::substitute(const TypeNode& type, |
751 |
|
const TypeNode& replacement) const { |
752 |
4 |
std::unordered_map<TypeNode, TypeNode> cache; |
753 |
4 |
return substitute(type, replacement, cache); |
754 |
|
} |
755 |
|
|
756 |
|
template <class Iterator1, class Iterator2> |
757 |
|
inline TypeNode |
758 |
17294 |
TypeNode::substitute(Iterator1 typesBegin, |
759 |
|
Iterator1 typesEnd, |
760 |
|
Iterator2 replacementsBegin, |
761 |
|
Iterator2 replacementsEnd) const { |
762 |
34588 |
std::unordered_map<TypeNode, TypeNode> cache; |
763 |
|
return substitute(typesBegin, typesEnd, |
764 |
34588 |
replacementsBegin, replacementsEnd, cache); |
765 |
|
} |
766 |
|
|
767 |
|
template <class Iterator1, class Iterator2> |
768 |
31352 |
TypeNode TypeNode::substitute( |
769 |
|
Iterator1 typesBegin, |
770 |
|
Iterator1 typesEnd, |
771 |
|
Iterator2 replacementsBegin, |
772 |
|
Iterator2 replacementsEnd, |
773 |
|
std::unordered_map<TypeNode, TypeNode>& cache) const |
774 |
|
{ |
775 |
|
// in cache? |
776 |
31352 |
std::unordered_map<TypeNode, TypeNode>::const_iterator i = cache.find(*this); |
777 |
31352 |
if(i != cache.end()) { |
778 |
4310 |
return (*i).second; |
779 |
|
} |
780 |
|
|
781 |
|
// otherwise compute |
782 |
27042 |
Assert(typesEnd - typesBegin == replacementsEnd - replacementsBegin) |
783 |
|
<< "Substitution iterator ranges must be equal size"; |
784 |
27042 |
Iterator1 j = find(typesBegin, typesEnd, *this); |
785 |
27042 |
if(j != typesEnd) { |
786 |
35024 |
TypeNode tn = *(replacementsBegin + (j - typesBegin)); |
787 |
17512 |
cache[*this] = tn; |
788 |
17512 |
return tn; |
789 |
9530 |
} else if(getNumChildren() == 0) { |
790 |
4324 |
cache[*this] = *this; |
791 |
4324 |
return *this; |
792 |
|
} else { |
793 |
10412 |
NodeBuilder nb(getKind()); |
794 |
5206 |
if(getMetaKind() == kind::metakind::PARAMETERIZED) { |
795 |
|
// push the operator |
796 |
|
nb << TypeNode(d_nv->d_children[0]); |
797 |
|
} |
798 |
19264 |
for (const TypeNode& tn : *this) |
799 |
|
{ |
800 |
14058 |
nb << tn.substitute( |
801 |
|
typesBegin, typesEnd, replacementsBegin, replacementsEnd, cache); |
802 |
|
} |
803 |
10412 |
TypeNode tn = nb.constructTypeNode(); |
804 |
5206 |
cache[*this] = tn; |
805 |
5206 |
return tn; |
806 |
|
} |
807 |
|
} |
808 |
|
|
809 |
5363553 |
inline size_t TypeNode::getNumChildren() const { |
810 |
5363553 |
return d_nv->getNumChildren(); |
811 |
|
} |
812 |
|
|
813 |
|
template <class T> |
814 |
449530453 |
inline const T& TypeNode::getConst() const { |
815 |
449530453 |
return d_nv->getConst<T>(); |
816 |
|
} |
817 |
|
|
818 |
43308010 |
inline TypeNode::TypeNode(const expr::NodeValue* ev) : |
819 |
43308010 |
d_nv(const_cast<expr::NodeValue*> (ev)) { |
820 |
43308010 |
Assert(d_nv != NULL) << "Expecting a non-NULL expression value!"; |
821 |
43308010 |
d_nv->inc(); |
822 |
43308010 |
} |
823 |
|
|
824 |
848803976 |
inline TypeNode::TypeNode(const TypeNode& typeNode) { |
825 |
848803976 |
Assert(typeNode.d_nv != NULL) << "Expecting a non-NULL expression value!"; |
826 |
848803976 |
d_nv = typeNode.d_nv; |
827 |
848803976 |
d_nv->inc(); |
828 |
848803976 |
} |
829 |
|
|
830 |
3485502734 |
inline TypeNode::~TypeNode() { |
831 |
1742751367 |
Assert(d_nv != NULL) << "Expecting a non-NULL expression value!"; |
832 |
1742751367 |
d_nv->dec(); |
833 |
1742751367 |
} |
834 |
|
|
835 |
|
inline void TypeNode::assignNodeValue(expr::NodeValue* ev) { |
836 |
|
d_nv = ev; |
837 |
|
d_nv->inc(); |
838 |
|
} |
839 |
|
|
840 |
810010741 |
inline TypeNode& TypeNode::operator=(const TypeNode& typeNode) { |
841 |
810010741 |
Assert(d_nv != NULL) << "Expecting a non-NULL expression value!"; |
842 |
810010741 |
Assert(typeNode.d_nv != NULL) |
843 |
|
<< "Expecting a non-NULL expression value on RHS!"; |
844 |
810010741 |
if(__builtin_expect( ( d_nv != typeNode.d_nv ), true )) { |
845 |
809642976 |
d_nv->dec(); |
846 |
809642976 |
d_nv = typeNode.d_nv; |
847 |
809642976 |
d_nv->inc(); |
848 |
|
} |
849 |
810010741 |
return *this; |
850 |
|
} |
851 |
|
|
852 |
|
template <class AttrKind> |
853 |
7827862 |
inline typename AttrKind::value_type TypeNode:: |
854 |
|
getAttribute(const AttrKind&) const { |
855 |
7827862 |
Assert(NodeManager::currentNM() != NULL) |
856 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
857 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
858 |
7827862 |
return NodeManager::currentNM()->getAttribute(d_nv, AttrKind()); |
859 |
|
} |
860 |
|
|
861 |
|
template <class AttrKind> |
862 |
8314045 |
inline bool TypeNode:: |
863 |
|
hasAttribute(const AttrKind&) const { |
864 |
8314045 |
Assert(NodeManager::currentNM() != NULL) |
865 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
866 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
867 |
8314045 |
return NodeManager::currentNM()->hasAttribute(d_nv, AttrKind()); |
868 |
|
} |
869 |
|
|
870 |
|
template <class AttrKind> |
871 |
|
inline bool TypeNode::getAttribute(const AttrKind&, typename AttrKind::value_type& ret) const { |
872 |
|
Assert(NodeManager::currentNM() != NULL) |
873 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
874 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
875 |
|
return NodeManager::currentNM()->getAttribute(d_nv, AttrKind(), ret); |
876 |
|
} |
877 |
|
|
878 |
|
template <class AttrKind> |
879 |
26034 |
inline void TypeNode:: |
880 |
|
setAttribute(const AttrKind&, const typename AttrKind::value_type& value) { |
881 |
26034 |
Assert(NodeManager::currentNM() != NULL) |
882 |
|
<< "There is no current cvc5::NodeManager associated to this thread.\n" |
883 |
|
"Perhaps a public-facing function is missing a NodeManagerScope ?"; |
884 |
26034 |
NodeManager::currentNM()->setAttribute(d_nv, AttrKind(), value); |
885 |
26034 |
} |
886 |
|
|
887 |
|
inline void TypeNode::printAst(std::ostream& out, int indent) const { |
888 |
|
d_nv->printAst(out, indent); |
889 |
|
} |
890 |
|
|
891 |
106351685 |
inline bool TypeNode::isBoolean() const { |
892 |
|
return |
893 |
106351685 |
( getKind() == kind::TYPE_CONSTANT && getConst<TypeConstant>() == BOOLEAN_TYPE ); |
894 |
|
} |
895 |
|
|
896 |
276658266 |
inline bool TypeNode::isInteger() const { |
897 |
|
return |
898 |
276658266 |
( getKind() == kind::TYPE_CONSTANT && getConst<TypeConstant>() == INTEGER_TYPE ); |
899 |
|
} |
900 |
|
|
901 |
13532004 |
inline bool TypeNode::isReal() const { |
902 |
|
return |
903 |
24442284 |
( getKind() == kind::TYPE_CONSTANT && getConst<TypeConstant>() == REAL_TYPE ) || |
904 |
24442284 |
isInteger(); |
905 |
|
} |
906 |
|
|
907 |
7435080 |
inline bool TypeNode::isString() const { |
908 |
14813312 |
return getKind() == kind::TYPE_CONSTANT && |
909 |
14813312 |
getConst<TypeConstant>() == STRING_TYPE; |
910 |
|
} |
911 |
|
|
912 |
|
/** Is this a regexp type */ |
913 |
2825155 |
inline bool TypeNode::isRegExp() const { |
914 |
5638544 |
return getKind() == kind::TYPE_CONSTANT && |
915 |
5638544 |
getConst<TypeConstant>() == REGEXP_TYPE; |
916 |
|
} |
917 |
|
|
918 |
41647 |
inline bool TypeNode::isRoundingMode() const { |
919 |
52106 |
return getKind() == kind::TYPE_CONSTANT && |
920 |
52106 |
getConst<TypeConstant>() == ROUNDINGMODE_TYPE; |
921 |
|
} |
922 |
|
|
923 |
1570796 |
inline bool TypeNode::isArray() const { |
924 |
1570796 |
return getKind() == kind::ARRAY_TYPE; |
925 |
|
} |
926 |
|
|
927 |
37277 |
inline TypeNode TypeNode::getArrayIndexType() const { |
928 |
37277 |
Assert(isArray()); |
929 |
37277 |
return (*this)[0]; |
930 |
|
} |
931 |
|
|
932 |
42204 |
inline TypeNode TypeNode::getArrayConstituentType() const { |
933 |
42204 |
Assert(isArray()); |
934 |
42204 |
return (*this)[1]; |
935 |
|
} |
936 |
|
|
937 |
240366 |
inline TypeNode TypeNode::getConstructorRangeType() const { |
938 |
240366 |
Assert(isConstructor()); |
939 |
240366 |
return (*this)[getNumChildren()-1]; |
940 |
|
} |
941 |
|
|
942 |
183253 |
inline TypeNode TypeNode::getSelectorDomainType() const |
943 |
|
{ |
944 |
183253 |
Assert(isSelector()); |
945 |
183253 |
return (*this)[0]; |
946 |
|
} |
947 |
|
|
948 |
607943 |
inline TypeNode TypeNode::getSelectorRangeType() const |
949 |
|
{ |
950 |
607943 |
Assert(isSelector()); |
951 |
607943 |
return (*this)[1]; |
952 |
|
} |
953 |
|
|
954 |
1632124 |
inline bool TypeNode::isSet() const { |
955 |
1632124 |
return getKind() == kind::SET_TYPE; |
956 |
|
} |
957 |
|
|
958 |
1619062 |
inline bool TypeNode::isSequence() const |
959 |
|
{ |
960 |
1619062 |
return getKind() == kind::SEQUENCE_TYPE; |
961 |
|
} |
962 |
|
|
963 |
706851 |
inline TypeNode TypeNode::getSetElementType() const { |
964 |
706851 |
Assert(isSet()); |
965 |
706851 |
return (*this)[0]; |
966 |
|
} |
967 |
|
|
968 |
9673647 |
inline bool TypeNode::isFunction() const { |
969 |
9673647 |
return getKind() == kind::FUNCTION_TYPE; |
970 |
|
} |
971 |
|
|
972 |
40547 |
inline bool TypeNode::isFunctionLike() const { |
973 |
|
return |
974 |
81012 |
getKind() == kind::FUNCTION_TYPE || |
975 |
80930 |
getKind() == kind::CONSTRUCTOR_TYPE || |
976 |
121454 |
getKind() == kind::SELECTOR_TYPE || |
977 |
80989 |
getKind() == kind::TESTER_TYPE; |
978 |
|
} |
979 |
|
|
980 |
119628 |
inline bool TypeNode::isPredicate() const { |
981 |
119628 |
return isFunction() && getRangeType().isBoolean(); |
982 |
|
} |
983 |
|
|
984 |
|
inline bool TypeNode::isPredicateLike() const { |
985 |
|
return isFunctionLike() && getRangeType().isBoolean(); |
986 |
|
} |
987 |
|
|
988 |
614656 |
inline TypeNode TypeNode::getRangeType() const { |
989 |
614656 |
if(isTester()) { |
990 |
|
return NodeManager::currentNM()->booleanType(); |
991 |
|
} |
992 |
614656 |
Assert(isFunction() || isConstructor() || isSelector()) |
993 |
|
<< "Cannot get range type of " << *this; |
994 |
614656 |
return (*this)[getNumChildren() - 1]; |
995 |
|
} |
996 |
|
|
997 |
|
/** Is this a floating-point type of with <code>exp</code> exponent bits |
998 |
|
and <code>sig</code> significand bits */ |
999 |
|
inline bool TypeNode::isFloatingPoint(unsigned exp, unsigned sig) const { |
1000 |
|
return (getKind() == kind::FLOATINGPOINT_TYPE |
1001 |
|
&& getConst<FloatingPointSize>().exponentWidth() == exp |
1002 |
|
&& getConst<FloatingPointSize>().significandWidth() == sig); |
1003 |
|
} |
1004 |
|
|
1005 |
|
/** Get the exponent size of this floating-point type */ |
1006 |
194 |
inline unsigned TypeNode::getFloatingPointExponentSize() const { |
1007 |
194 |
Assert(isFloatingPoint()); |
1008 |
194 |
return getConst<FloatingPointSize>().exponentWidth(); |
1009 |
|
} |
1010 |
|
|
1011 |
|
/** Get the significand size of this floating-point type */ |
1012 |
194 |
inline unsigned TypeNode::getFloatingPointSignificandSize() const { |
1013 |
194 |
Assert(isFloatingPoint()); |
1014 |
194 |
return getConst<FloatingPointSize>().significandWidth(); |
1015 |
|
} |
1016 |
|
|
1017 |
|
#ifdef CVC5_DEBUG |
1018 |
|
/** |
1019 |
|
* Pretty printer for use within gdb. This is not intended to be used |
1020 |
|
* outside of gdb. This writes to the Warning() stream and immediately |
1021 |
|
* flushes the stream. |
1022 |
|
* |
1023 |
|
* Note that this function cannot be a template, since the compiler |
1024 |
|
* won't instantiate it. Even if we explicitly instantiate. (Odd?) |
1025 |
|
* So we implement twice. We mark as __attribute__((used)) so that |
1026 |
|
* GCC emits code for it even though static analysis indicates it's |
1027 |
|
* never called. |
1028 |
|
* |
1029 |
|
* Tim's Note: I moved this into the node.h file because this allows gdb |
1030 |
|
* to find the symbol, and use it, which is the first standard this code needs |
1031 |
|
* to meet. A cleaner solution is welcomed. |
1032 |
|
*/ |
1033 |
|
static void __attribute__((used)) debugPrintTypeNode(const TypeNode& n) { |
1034 |
|
Warning() << Node::setdepth(-1) << Node::dag(true) |
1035 |
|
<< Node::setlanguage(Language::LANG_AST) << n << std::endl; |
1036 |
|
Warning().flush(); |
1037 |
|
} |
1038 |
|
static void __attribute__((used)) debugPrintTypeNodeNoDag(const TypeNode& n) { |
1039 |
|
Warning() << Node::setdepth(-1) << Node::dag(false) |
1040 |
|
<< Node::setlanguage(Language::LANG_AST) << n << std::endl; |
1041 |
|
Warning().flush(); |
1042 |
|
} |
1043 |
|
static void __attribute__((used)) debugPrintRawTypeNode(const TypeNode& n) { |
1044 |
|
n.printAst(Warning(), 0); |
1045 |
|
Warning().flush(); |
1046 |
|
} |
1047 |
|
#endif /* CVC5_DEBUG */ |
1048 |
|
|
1049 |
|
} // namespace cvc5 |
1050 |
|
|
1051 |
|
#endif /* CVC5__NODE_H */ |