1 /********************* */
2 /*! \file type_node.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Morgan Deters, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 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.\endverbatim
11 **
12 ** \brief Reference-counted encapsulation of a pointer to node information.
13 **
14 ** Reference-counted encapsulation of a pointer to node information.
15 **/
16 #include "expr/type_node.h"
17
18 #include <vector>
19
20 #include "expr/node_manager_attributes.h"
21 #include "expr/type_properties.h"
22 #include "options/base_options.h"
23 #include "options/expr_options.h"
24 #include "options/quantifiers_options.h"
25 #include "options/uf_options.h"
26
27 using namespace std;
28
29 namespace CVC4 {
30
31 TypeNode TypeNode::s_null( &expr::NodeValue::null() );
32
substitute(const TypeNode & type,const TypeNode & replacement,std::unordered_map<TypeNode,TypeNode,HashFunction> & cache) const33 TypeNode TypeNode::substitute(const TypeNode& type,
34 const TypeNode& replacement,
35 std::unordered_map<TypeNode, TypeNode, HashFunction>& cache) const {
36 // in cache?
37 std::unordered_map<TypeNode, TypeNode, HashFunction>::const_iterator i = cache.find(*this);
38 if(i != cache.end()) {
39 return (*i).second;
40 }
41
42 // otherwise compute
43 NodeBuilder<> nb(getKind());
44 if(getMetaKind() == kind::metakind::PARAMETERIZED) {
45 // push the operator
46 nb << TypeNode(d_nv->d_children[0]);
47 }
48 for(TypeNode::const_iterator i = begin(),
49 iend = end();
50 i != iend;
51 ++i) {
52 if(*i == type) {
53 nb << replacement;
54 } else {
55 (*i).substitute(type, replacement);
56 }
57 }
58
59 // put in cache
60 TypeNode tn = nb.constructTypeNode();
61 cache[*this] = tn;
62 return tn;
63 }
64
getCardinality() const65 Cardinality TypeNode::getCardinality() const {
66 return kind::getCardinality(*this);
67 }
68
69 /** Attribute true for types that are interpreted as finite */
70 struct IsInterpretedFiniteTag
71 {
72 };
73 struct IsInterpretedFiniteComputedTag
74 {
75 };
76 typedef expr::Attribute<IsInterpretedFiniteTag, bool> IsInterpretedFiniteAttr;
77 typedef expr::Attribute<IsInterpretedFiniteComputedTag, bool>
78 IsInterpretedFiniteComputedAttr;
79
isInterpretedFinite()80 bool TypeNode::isInterpretedFinite()
81 {
82 // check it is already cached
83 if (!getAttribute(IsInterpretedFiniteComputedAttr()))
84 {
85 bool isInterpretedFinite = false;
86 if (isSort())
87 {
88 // If the finite model finding flag is set, we treat uninterpreted sorts
89 // as finite. If it is not set, we treat them implicitly as infinite
90 // sorts (that is, their cardinality is not constrained to be finite).
91 isInterpretedFinite = options::finiteModelFind();
92 }
93 else if (isBitVector() || isFloatingPoint())
94 {
95 isInterpretedFinite = true;
96 }
97 else if (isDatatype())
98 {
99 TypeNode tn = *this;
100 const Datatype& dt = getDatatype();
101 isInterpretedFinite = dt.isInterpretedFinite(tn.toType());
102 }
103 else if (isArray())
104 {
105 TypeNode tnc = getArrayConstituentType();
106 if (!tnc.isInterpretedFinite())
107 {
108 // arrays with consistuent type that is infinite are infinite
109 isInterpretedFinite = false;
110 }
111 else if (getArrayIndexType().isInterpretedFinite())
112 {
113 // arrays with both finite consistuent and index types are finite
114 isInterpretedFinite = true;
115 }
116 else
117 {
118 // If the consistuent type of the array has cardinality one, then the
119 // array type has cardinality one, independent of the index type.
120 isInterpretedFinite = tnc.getCardinality().isOne();
121 }
122 }
123 else if (isSet())
124 {
125 isInterpretedFinite = getSetElementType().isInterpretedFinite();
126 }
127 else if (isFunction())
128 {
129 isInterpretedFinite = true;
130 TypeNode tnr = getRangeType();
131 if (!tnr.isInterpretedFinite())
132 {
133 isInterpretedFinite = false;
134 }
135 else
136 {
137 std::vector<TypeNode> argTypes = getArgTypes();
138 for (unsigned i = 0, nargs = argTypes.size(); i < nargs; i++)
139 {
140 if (!argTypes[i].isInterpretedFinite())
141 {
142 isInterpretedFinite = false;
143 break;
144 }
145 }
146 if (!isInterpretedFinite)
147 {
148 // similar to arrays, functions are finite if their range type
149 // has cardinality one, regardless of the arguments.
150 isInterpretedFinite = tnr.getCardinality().isOne();
151 }
152 }
153 }
154 else
155 {
156 // by default, compute the exact cardinality for the type and check
157 // whether it is finite. This should be avoided in general, since
158 // computing cardinalities for types can be highly expensive.
159 isInterpretedFinite = getCardinality().isFinite();
160 }
161 setAttribute(IsInterpretedFiniteAttr(), isInterpretedFinite);
162 setAttribute(IsInterpretedFiniteComputedAttr(), true);
163 return isInterpretedFinite;
164 }
165 return getAttribute(IsInterpretedFiniteAttr());
166 }
167
168 /** Attribute true for types that are closed enumerable */
169 struct IsClosedEnumerableTag
170 {
171 };
172 struct IsClosedEnumerableComputedTag
173 {
174 };
175 typedef expr::Attribute<IsClosedEnumerableTag, bool> IsClosedEnumerableAttr;
176 typedef expr::Attribute<IsClosedEnumerableComputedTag, bool>
177 IsClosedEnumerableComputedAttr;
178
isClosedEnumerable()179 bool TypeNode::isClosedEnumerable()
180 {
181 // check it is already cached
182 if (!getAttribute(IsClosedEnumerableComputedAttr()))
183 {
184 bool ret = true;
185 if (isArray() || isSort() || isCodatatype() || isFunction())
186 {
187 ret = false;
188 }
189 else if (isSet())
190 {
191 ret = getSetElementType().isClosedEnumerable();
192 }
193 else if (isDatatype())
194 {
195 // avoid infinite loops: initially set to true
196 setAttribute(IsClosedEnumerableAttr(), ret);
197 setAttribute(IsClosedEnumerableComputedAttr(), true);
198 TypeNode tn = *this;
199 const Datatype& dt = getDatatype();
200 for (unsigned i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
201 {
202 for (unsigned j = 0, nargs = dt[i].getNumArgs(); j < nargs; j++)
203 {
204 TypeNode ctn = TypeNode::fromType(dt[i][j].getRangeType());
205 if (tn != ctn && !ctn.isClosedEnumerable())
206 {
207 ret = false;
208 break;
209 }
210 }
211 if (!ret)
212 {
213 break;
214 }
215 }
216 }
217 setAttribute(IsClosedEnumerableAttr(), ret);
218 setAttribute(IsClosedEnumerableComputedAttr(), true);
219 return ret;
220 }
221 return getAttribute(IsClosedEnumerableAttr());
222 }
223
isFirstClass() const224 bool TypeNode::isFirstClass() const {
225 return ( getKind() != kind::FUNCTION_TYPE || options::ufHo() ) &&
226 getKind() != kind::CONSTRUCTOR_TYPE &&
227 getKind() != kind::SELECTOR_TYPE &&
228 getKind() != kind::TESTER_TYPE &&
229 getKind() != kind::SEXPR_TYPE &&
230 ( getKind() != kind::TYPE_CONSTANT ||
231 getConst<TypeConstant>() != REGEXP_TYPE );
232 }
233
isWellFounded() const234 bool TypeNode::isWellFounded() const {
235 return kind::isWellFounded(*this);
236 }
237
mkGroundTerm() const238 Node TypeNode::mkGroundTerm() const {
239 return kind::mkGroundTerm(*this);
240 }
241
isSubtypeOf(TypeNode t) const242 bool TypeNode::isSubtypeOf(TypeNode t) const {
243 if(*this == t) {
244 return true;
245 }
246 if(getKind() == kind::TYPE_CONSTANT) {
247 switch(getConst<TypeConstant>()) {
248 case INTEGER_TYPE:
249 return t.getKind() == kind::TYPE_CONSTANT && t.getConst<TypeConstant>() == REAL_TYPE;
250 default:
251 return false;
252 }
253 }
254 if(isSet() && t.isSet()) {
255 return getSetElementType().isSubtypeOf(t.getSetElementType());
256 }
257 // this should only return true for types T1, T2 where we handle equalities between T1 and T2
258 // (more cases go here, if we want to support such cases)
259 return false;
260 }
261
isComparableTo(TypeNode t) const262 bool TypeNode::isComparableTo(TypeNode t) const {
263 if(*this == t) {
264 return true;
265 }
266 if(isSubtypeOf(NodeManager::currentNM()->realType())) {
267 return t.isSubtypeOf(NodeManager::currentNM()->realType());
268 }
269 if(isSet() && t.isSet()) {
270 return getSetElementType().isComparableTo(t.getSetElementType());
271 }
272 return false;
273 }
274
getBaseType() const275 TypeNode TypeNode::getBaseType() const {
276 TypeNode realt = NodeManager::currentNM()->realType();
277 if (isSubtypeOf(realt)) {
278 return realt;
279 } else if (isParametricDatatype()) {
280 vector<Type> v;
281 for(size_t i = 1; i < getNumChildren(); ++i) {
282 v.push_back((*this)[i].getBaseType().toType());
283 }
284 TypeNode tn = TypeNode::fromType((*this)[0].getDatatype().getDatatypeType(v));
285 return tn;
286 }
287 return *this;
288 }
289
getArgTypes() const290 std::vector<TypeNode> TypeNode::getArgTypes() const {
291 vector<TypeNode> args;
292 if(isTester()) {
293 Assert(getNumChildren() == 1);
294 args.push_back((*this)[0]);
295 } else {
296 Assert(isFunction() || isConstructor() || isSelector());
297 for(unsigned i = 0, i_end = getNumChildren() - 1; i < i_end; ++i) {
298 args.push_back((*this)[i]);
299 }
300 }
301 return args;
302 }
303
getParamTypes() const304 std::vector<TypeNode> TypeNode::getParamTypes() const {
305 vector<TypeNode> params;
306 Assert(isParametricDatatype());
307 for(unsigned i = 1, i_end = getNumChildren(); i < i_end; ++i) {
308 params.push_back((*this)[i]);
309 }
310 return params;
311 }
312
313
314 /** Is this a tuple type? */
isTuple() const315 bool TypeNode::isTuple() const {
316 return ( getKind() == kind::DATATYPE_TYPE && getDatatype().isTuple() );
317 }
318
319 /** Is this a record type? */
isRecord() const320 bool TypeNode::isRecord() const {
321 return ( getKind() == kind::DATATYPE_TYPE && getDatatype().isRecord() );
322 }
323
getTupleLength() const324 size_t TypeNode::getTupleLength() const {
325 Assert(isTuple());
326 const Datatype& dt = getDatatype();
327 Assert(dt.getNumConstructors()==1);
328 return dt[0].getNumArgs();
329 }
330
getTupleTypes() const331 vector<TypeNode> TypeNode::getTupleTypes() const {
332 Assert(isTuple());
333 const Datatype& dt = getDatatype();
334 Assert(dt.getNumConstructors()==1);
335 vector<TypeNode> types;
336 for(unsigned i = 0; i < dt[0].getNumArgs(); ++i) {
337 types.push_back(TypeNode::fromType(dt[0][i].getRangeType()));
338 }
339 return types;
340 }
341
getRecord() const342 const Record& TypeNode::getRecord() const {
343 Assert(isRecord());
344 const Datatype & dt = getDatatype();
345 return *(dt.getRecord());
346 //return getAttribute(expr::DatatypeRecordAttr()).getConst<Record>();
347 }
348
getSExprTypes() const349 vector<TypeNode> TypeNode::getSExprTypes() const {
350 Assert(isSExpr());
351 vector<TypeNode> types;
352 for(unsigned i = 0, i_end = getNumChildren(); i < i_end; ++i) {
353 types.push_back((*this)[i]);
354 }
355 return types;
356 }
357
358 /** Is this an instantiated datatype type */
isInstantiatedDatatype() const359 bool TypeNode::isInstantiatedDatatype() const {
360 if(getKind() == kind::DATATYPE_TYPE) {
361 return true;
362 }
363 if(getKind() != kind::PARAMETRIC_DATATYPE) {
364 return false;
365 }
366 const Datatype& dt = (*this)[0].getDatatype();
367 unsigned n = dt.getNumParameters();
368 Assert(n < getNumChildren());
369 for(unsigned i = 0; i < n; ++i) {
370 if(TypeNode::fromType(dt.getParameter(i)) == (*this)[i + 1]) {
371 return false;
372 }
373 }
374 return true;
375 }
376
377 /** Is this an instantiated datatype parameter */
isParameterInstantiatedDatatype(unsigned n) const378 bool TypeNode::isParameterInstantiatedDatatype(unsigned n) const {
379 AssertArgument(getKind() == kind::PARAMETRIC_DATATYPE, *this);
380 const Datatype& dt = (*this)[0].getDatatype();
381 AssertArgument(n < dt.getNumParameters(), *this);
382 return TypeNode::fromType(dt.getParameter(n)) != (*this)[n + 1];
383 }
384
leastCommonTypeNode(TypeNode t0,TypeNode t1)385 TypeNode TypeNode::leastCommonTypeNode(TypeNode t0, TypeNode t1){
386 return commonTypeNode( t0, t1, true );
387 }
388
mostCommonTypeNode(TypeNode t0,TypeNode t1)389 TypeNode TypeNode::mostCommonTypeNode(TypeNode t0, TypeNode t1){
390 return commonTypeNode( t0, t1, false );
391 }
392
commonTypeNode(TypeNode t0,TypeNode t1,bool isLeast)393 TypeNode TypeNode::commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast) {
394 Assert( NodeManager::currentNM() != NULL,
395 "There is no current CVC4::NodeManager associated to this thread.\n"
396 "Perhaps a public-facing function is missing a NodeManagerScope ?" );
397
398 Assert(!t0.isNull());
399 Assert(!t1.isNull());
400
401 if(__builtin_expect( (t0 == t1), true )) {
402 return t0;
403 }
404
405 // t0 != t1 &&
406 if(t0.getKind() == kind::TYPE_CONSTANT) {
407 switch(t0.getConst<TypeConstant>()) {
408 case INTEGER_TYPE:
409 if(t1.isInteger()) {
410 // t0 == IntegerType && t1.isInteger()
411 return t0; //IntegerType
412 } else if(t1.isReal()) {
413 // t0 == IntegerType && t1.isReal() && !t1.isInteger()
414 return isLeast ? t1 : t0; // RealType
415 } else {
416 return TypeNode(); // null type
417 }
418 case REAL_TYPE:
419 if(t1.isReal()) {
420 return isLeast ? t0 : t1; // RealType
421 } else {
422 return TypeNode(); // null type
423 }
424 default:
425 return TypeNode(); // null type
426 }
427 } else if(t1.getKind() == kind::TYPE_CONSTANT) {
428 return commonTypeNode(t1, t0, isLeast); // decrease the number of special cases
429 }
430
431 // t0 != t1 &&
432 // t0.getKind() == kind::TYPE_CONSTANT &&
433 // t1.getKind() == kind::TYPE_CONSTANT
434 switch(t0.getKind()) {
435 case kind::BITVECTOR_TYPE:
436 case kind::FLOATINGPOINT_TYPE:
437 case kind::SORT_TYPE:
438 case kind::CONSTRUCTOR_TYPE:
439 case kind::SELECTOR_TYPE:
440 case kind::TESTER_TYPE:
441 case kind::FUNCTION_TYPE:
442 case kind::ARRAY_TYPE:
443 case kind::DATATYPE_TYPE:
444 case kind::PARAMETRIC_DATATYPE:
445 return TypeNode();
446 case kind::SET_TYPE: {
447 // take the least common subtype of element types
448 TypeNode elementType;
449 if(t1.isSet() && !(elementType = commonTypeNode(t0[0], t1[0], isLeast)).isNull() ) {
450 return NodeManager::currentNM()->mkSetType(elementType);
451 } else {
452 return TypeNode();
453 }
454 }
455 case kind::SEXPR_TYPE:
456 Unimplemented("haven't implemented leastCommonType for symbolic expressions yet");
457 default:
458 Unimplemented("don't have a commonType for types `%s' and `%s'", t0.toString().c_str(), t1.toString().c_str());
459 }
460 }
461
getEnsureTypeCondition(Node n,TypeNode tn)462 Node TypeNode::getEnsureTypeCondition( Node n, TypeNode tn ) {
463 TypeNode ntn = n.getType();
464 Assert( ntn.isComparableTo( tn ) );
465 if( !ntn.isSubtypeOf( tn ) ){
466 if( tn.isInteger() ){
467 if( tn.isSubtypeOf( ntn ) ){
468 return NodeManager::currentNM()->mkNode( kind::IS_INTEGER, n );
469 }
470 }else if( tn.isDatatype() && ntn.isDatatype() ){
471 if( tn.isTuple() && ntn.isTuple() ){
472 const Datatype& dt1 = tn.getDatatype();
473 const Datatype& dt2 = ntn.getDatatype();
474 if( dt1[0].getNumArgs()==dt2[0].getNumArgs() ){
475 std::vector< Node > conds;
476 for( unsigned i=0; i<dt2[0].getNumArgs(); i++ ){
477 Node s = NodeManager::currentNM()->mkNode( kind::APPLY_SELECTOR_TOTAL, Node::fromExpr( dt2[0][i].getSelector() ), n );
478 Node etc = getEnsureTypeCondition( s, TypeNode::fromType( dt1[0][i].getRangeType() ) );
479 if( etc.isNull() ){
480 return Node::null();
481 }else{
482 conds.push_back( etc );
483 }
484 }
485 if( conds.empty() ){
486 return NodeManager::currentNM()->mkConst( true );
487 }else if( conds.size()==1 ){
488 return conds[0];
489 }else{
490 return NodeManager::currentNM()->mkNode( kind::AND, conds );
491 }
492 }
493 }
494 }
495 return Node::null();
496 }else{
497 return NodeManager::currentNM()->mkConst( true );
498 }
499 }
500
501 /** Is this a sort kind */
isSort() const502 bool TypeNode::isSort() const {
503 return ( getKind() == kind::SORT_TYPE && !hasAttribute(expr::SortArityAttr()) );
504 }
505
506 /** Is this a sort constructor kind */
isSortConstructor() const507 bool TypeNode::isSortConstructor() const {
508 return getKind() == kind::SORT_TYPE && hasAttribute(expr::SortArityAttr());
509 }
510
toString() const511 std::string TypeNode::toString() const {
512 std::stringstream ss;
513 OutputLanguage outlang = (this == &s_null) ? language::output::LANG_AUTO : options::outputLanguage();
514 d_nv->toStream(ss, -1, false, 0, outlang);
515 return ss.str();
516 }
517
518
519 }/* CVC4 namespace */
520