1 /********************* */
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
12 ** \brief A class representing a Datatype definition
14 ** A class representing a Datatype definition for the theory of
15 ** inductive datatypes.
17 #include "expr/datatype.h"
22 #include "base/check.h"
23 #include "expr/attribute.h"
24 #include "expr/dtype.h"
25 #include "expr/expr_manager.h"
26 #include "expr/expr_manager_scope.h"
27 #include "expr/node.h"
28 #include "expr/node_algorithm.h"
29 #include "expr/node_manager.h"
30 #include "expr/type.h"
31 #include "expr/type_matcher.h"
32 #include "options/datatypes_options.h"
33 #include "options/set_language.h"
34 #include "theory/type_enumerator.h"
42 ExprManagerScope
ems(*d_em
);
44 d_constructors
.clear();
48 Datatype::Datatype(ExprManager
* em
, std::string name
, bool isCo
)
55 ExprManagerScope
ems(*d_em
);
56 d_internal
= std::make_shared
<DType
>(name
, isCo
);
59 Datatype::Datatype(ExprManager
* em
,
61 const std::vector
<Type
>& params
,
69 ExprManagerScope
ems(*d_em
);
70 std::vector
<TypeNode
> paramsn
;
71 for (const Type
& t
: params
)
73 paramsn
.push_back(TypeNode::fromType(t
));
75 d_internal
= std::make_shared
<DType
>(name
, paramsn
, isCo
);
78 const Datatype
& Datatype::datatypeOf(Expr item
) {
79 ExprManagerScope
ems(item
);
80 TypeNode t
= Node::fromExpr(item
).getType();
82 case kind::CONSTRUCTOR_TYPE
:
83 return DatatypeType(t
[t
.getNumChildren() - 1].toType()).getDatatype();
84 case kind::SELECTOR_TYPE
:
85 case kind::TESTER_TYPE
:
86 return DatatypeType(t
[0].toType()).getDatatype();
88 Unhandled() << "arg must be a datatype constructor, selector, or tester";
92 size_t Datatype::indexOf(Expr item
) {
93 ExprManagerScope
ems(item
);
94 PrettyCheckArgument(item
.getType().isConstructor() ||
95 item
.getType().isTester() ||
96 item
.getType().isSelector(),
98 "arg must be a datatype constructor, selector, or tester");
99 return indexOfInternal(item
);
102 size_t Datatype::indexOfInternal(Expr item
)
104 TNode n
= Node::fromExpr(item
);
105 if( item
.getKind()==kind::APPLY_TYPE_ASCRIPTION
){
106 return indexOf( item
[0] );
108 Assert(n
.hasAttribute(DTypeIndexAttr()));
109 return n
.getAttribute(DTypeIndexAttr());
113 size_t Datatype::cindexOf(Expr item
) {
114 ExprManagerScope
ems(item
);
115 PrettyCheckArgument(item
.getType().isSelector(),
117 "arg must be a datatype selector");
118 return cindexOfInternal(item
);
120 size_t Datatype::cindexOfInternal(Expr item
)
122 TNode n
= Node::fromExpr(item
);
123 if( item
.getKind()==kind::APPLY_TYPE_ASCRIPTION
){
124 return cindexOf( item
[0] );
126 Assert(n
.hasAttribute(DTypeConsIndexAttr()));
127 return n
.getAttribute(DTypeConsIndexAttr());
131 void Datatype::resolve(const std::map
<std::string
, DatatypeType
>& resolutions
,
132 const std::vector
<Type
>& placeholders
,
133 const std::vector
<Type
>& replacements
,
134 const std::vector
<SortConstructorType
>& paramTypes
,
135 const std::vector
<DatatypeType
>& paramReplacements
)
137 PrettyCheckArgument(!isResolved(), this, "cannot resolve a Datatype twice");
138 PrettyCheckArgument(resolutions
.find(getName()) != resolutions
.end(),
140 "Datatype::resolve(): resolutions doesn't contain me!");
141 PrettyCheckArgument(placeholders
.size() == replacements
.size(), placeholders
,
142 "placeholders and replacements must be the same size");
143 PrettyCheckArgument(paramTypes
.size() == paramReplacements
.size(), paramTypes
,
144 "paramTypes and paramReplacements must be the same size");
145 PrettyCheckArgument(getNumConstructors() > 0, *this, "cannot resolve a Datatype that has no constructors");
147 // we're using some internals, so we have to make sure that the Datatype's
148 // ExprManager is active
149 ExprManagerScope
ems(*d_em
);
151 Trace("datatypes") << "Datatype::resolve: " << getName()
152 << ", #placeholders=" << placeholders
.size() << std::endl
;
154 std::map
<std::string
, TypeNode
> resolutionsn
;
155 std::vector
<TypeNode
> placeholdersn
;
156 std::vector
<TypeNode
> replacementsn
;
157 std::vector
<TypeNode
> paramTypesn
;
158 std::vector
<TypeNode
> paramReplacementsn
;
159 for (const std::pair
<const std::string
, DatatypeType
>& r
: resolutions
)
161 resolutionsn
[r
.first
] = TypeNode::fromType(r
.second
);
163 for (const Type
& t
: placeholders
)
165 placeholdersn
.push_back(TypeNode::fromType(t
));
167 for (const Type
& t
: replacements
)
169 replacementsn
.push_back(TypeNode::fromType(t
));
171 for (const Type
& t
: paramTypes
)
173 paramTypesn
.push_back(TypeNode::fromType(t
));
175 for (const Type
& t
: paramReplacements
)
177 paramReplacementsn
.push_back(TypeNode::fromType(t
));
179 bool res
= d_internal
->resolve(resolutionsn
,
186 IllegalArgument(*this,
187 "could not resolve datatype that is not well formed");
189 Trace("dt-debug") << "Datatype::resolve: finished " << getName() << " "
190 << d_constructors
.size() << std::endl
;
191 AlwaysAssert(isResolved());
193 d_self
= d_internal
->getTypeNode().toType();
194 for (DatatypeConstructor
& c
: d_constructors
)
196 AlwaysAssert(c
.isResolved());
197 c
.d_constructor
= c
.d_internal
->getConstructor().toExpr();
198 for (size_t i
= 0, nargs
= c
.getNumArgs(); i
< nargs
; i
++)
200 AlwaysAssert(c
.d_args
[i
].isResolved());
201 c
.d_args
[i
].d_selector
= c
.d_args
[i
].d_internal
->getSelector().toExpr();
206 std::vector
< std::pair
<std::string
, Type
> > fields
;
207 for( unsigned i
=0; i
<(*this)[0].getNumArgs(); i
++ ){
208 fields
.push_back( std::pair
<std::string
, Type
>( (*this)[0][i
].getName(), (*this)[0][i
].getRangeType() ) );
210 d_record
= new Record(fields
);
214 void Datatype::addConstructor(const DatatypeConstructor
& c
) {
215 Trace("dt-debug") << "Datatype::addConstructor" << std::endl
;
217 !isResolved(), this, "cannot add a constructor to a finalized Datatype");
218 d_constructors
.push_back(c
);
219 d_internal
->addConstructor(c
.d_internal
);
220 Trace("dt-debug") << "Datatype::addConstructor: finished" << std::endl
;
224 void Datatype::setSygus( Type st
, Expr bvl
, bool allow_const
, bool allow_all
){
226 !isResolved(), this, "cannot set sygus type to a finalized Datatype");
227 TypeNode stn
= TypeNode::fromType(st
);
228 Node bvln
= Node::fromExpr(bvl
);
229 d_internal
->setSygus(stn
, bvln
, allow_const
, allow_all
);
232 void Datatype::addSygusConstructor(Expr op
,
233 const std::string
& cname
,
234 const std::vector
<Type
>& cargs
,
235 std::shared_ptr
<SygusPrintCallback
> spc
,
238 // avoid name clashes
239 std::stringstream ss
;
240 ss
<< getName() << "_" << getNumConstructors() << "_" << cname
;
241 std::string name
= ss
.str();
242 std::string
testerId("is-");
243 testerId
.append(name
);
244 unsigned cweight
= weight
>= 0 ? weight
: (cargs
.empty() ? 0 : 1);
245 DatatypeConstructor
c(name
, testerId
, cweight
);
247 for( unsigned j
=0; j
<cargs
.size(); j
++ ){
248 Debug("parser-sygus-debug") << " arg " << j
<< " : " << cargs
[j
] << std::endl
;
249 std::stringstream sname
;
250 sname
<< name
<< "_" << j
;
251 c
.addArg(sname
.str(), cargs
[j
]);
256 void Datatype::addSygusConstructor(Kind k
,
257 const std::string
& cname
,
258 const std::vector
<Type
>& cargs
,
259 std::shared_ptr
<SygusPrintCallback
> spc
,
262 ExprManagerScope
ems(*d_em
);
263 Expr op
= d_em
->operatorOf(k
);
264 addSygusConstructor(op
, cname
, cargs
, spc
, weight
);
267 void Datatype::setTuple() {
269 !isResolved(), this, "cannot set tuple to a finalized Datatype");
270 d_internal
->setTuple();
273 void Datatype::setRecord() {
275 !isResolved(), this, "cannot set record to a finalized Datatype");
279 Cardinality
Datatype::getCardinality(Type t
) const
281 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
282 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
283 ExprManagerScope
ems(d_self
);
284 TypeNode tn
= TypeNode::fromType(t
);
285 return d_internal
->getCardinality(tn
);
288 Cardinality
Datatype::getCardinality() const
290 PrettyCheckArgument(!isParametric(), this, "for getCardinality, this datatype cannot be parametric");
291 ExprManagerScope
ems(d_self
);
292 return d_internal
->getCardinality();
295 bool Datatype::isRecursiveSingleton(Type t
) const
297 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
298 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
299 ExprManagerScope
ems(d_self
);
300 TypeNode tn
= TypeNode::fromType(t
);
301 return d_internal
->isRecursiveSingleton(tn
);
304 bool Datatype::isRecursiveSingleton() const
306 PrettyCheckArgument(!isParametric(), this, "for isRecursiveSingleton, this datatype cannot be parametric");
307 ExprManagerScope
ems(d_self
);
308 return d_internal
->isRecursiveSingleton();
311 unsigned Datatype::getNumRecursiveSingletonArgTypes(Type t
) const
313 Assert(isRecursiveSingleton(t
));
314 ExprManagerScope
ems(d_self
);
315 TypeNode tn
= TypeNode::fromType(t
);
316 return d_internal
->getNumRecursiveSingletonArgTypes(tn
);
319 unsigned Datatype::getNumRecursiveSingletonArgTypes() const
321 PrettyCheckArgument(!isParametric(), this, "for getNumRecursiveSingletonArgTypes, this datatype cannot be parametric");
322 ExprManagerScope
ems(d_self
);
323 return d_internal
->getNumRecursiveSingletonArgTypes();
326 Type
Datatype::getRecursiveSingletonArgType(Type t
, unsigned i
) const
328 Assert(isRecursiveSingleton(t
));
329 ExprManagerScope
ems(d_self
);
330 TypeNode tn
= TypeNode::fromType(t
);
331 return d_internal
->getRecursiveSingletonArgType(tn
, i
).toType();
334 Type
Datatype::getRecursiveSingletonArgType(unsigned i
) const
336 PrettyCheckArgument(!isParametric(), this, "for getRecursiveSingletonArgType, this datatype cannot be parametric");
337 ExprManagerScope
ems(d_self
);
338 return d_internal
->getRecursiveSingletonArgType(i
).toType();
341 bool Datatype::isFinite(Type t
) const
343 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
344 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
345 ExprManagerScope
ems(d_self
);
346 TypeNode tn
= TypeNode::fromType(t
);
347 return d_internal
->isFinite(tn
);
349 bool Datatype::isFinite() const
351 PrettyCheckArgument(isResolved() && !isParametric(), this, "this datatype must be resolved and not parametric");
352 ExprManagerScope
ems(d_self
);
353 return d_internal
->isFinite();
356 bool Datatype::isInterpretedFinite(Type t
) const
358 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
359 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
360 ExprManagerScope
ems(d_self
);
361 TypeNode tn
= TypeNode::fromType(t
);
362 return d_internal
->isInterpretedFinite(tn
);
364 bool Datatype::isInterpretedFinite() const
366 PrettyCheckArgument(isResolved() && !isParametric(), this, "this datatype must be resolved and not parametric");
367 ExprManagerScope
ems(d_self
);
368 return d_internal
->isInterpretedFinite();
371 bool Datatype::isWellFounded() const
373 ExprManagerScope
ems(d_self
);
374 return d_internal
->isWellFounded();
377 Expr
Datatype::mkGroundTerm(Type t
) const
379 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
380 ExprManagerScope
ems(d_self
);
381 TypeNode tn
= TypeNode::fromType(t
);
382 Node gterm
= d_internal
->mkGroundTerm(tn
);
386 "datatype is not well-founded, cannot construct a ground term!");
387 return gterm
.toExpr();
390 Expr
Datatype::mkGroundValue(Type t
) const
392 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
393 ExprManagerScope
ems(d_self
);
394 TypeNode tn
= TypeNode::fromType(t
);
395 Node gvalue
= d_internal
->mkGroundValue(tn
);
399 "datatype is not well-founded, cannot construct a ground value!");
400 return gvalue
.toExpr();
403 DatatypeType
Datatype::getDatatypeType() const
405 PrettyCheckArgument(isResolved(), *this, "Datatype must be resolved to get its DatatypeType");
406 ExprManagerScope
ems(d_self
);
407 Type self
= d_internal
->getTypeNode().toType();
408 PrettyCheckArgument(!self
.isNull(), *this);
409 return DatatypeType(self
);
412 DatatypeType
Datatype::getDatatypeType(const std::vector
<Type
>& params
) const
414 PrettyCheckArgument(isResolved(), *this, "Datatype must be resolved to get its DatatypeType");
415 ExprManagerScope
ems(d_self
);
416 Type self
= d_internal
->getTypeNode().toType();
417 PrettyCheckArgument(!self
.isNull() && DatatypeType(self
).isParametric(),
419 return DatatypeType(self
).instantiate(params
);
422 bool Datatype::operator==(const Datatype
& other
) const
424 // two datatypes are == iff the name is the same and they have
425 // exactly matching constructors (in the same order)
433 const DatatypeConstructor
& Datatype::operator[](size_t index
) const {
434 PrettyCheckArgument(index
< getNumConstructors(), index
, "index out of bounds");
435 return d_constructors
[index
];
438 const DatatypeConstructor
& Datatype::operator[](std::string name
) const {
439 for(const_iterator i
= begin(); i
!= end(); ++i
) {
440 if((*i
).getName() == name
) {
444 std::string dname
= getName();
445 IllegalArgument(name
,
446 "No such constructor `%s' of datatype `%s'",
451 Expr
Datatype::getConstructor(std::string name
) const {
452 return (*this)[name
].getConstructor();
455 Type
Datatype::getSygusType() const {
456 return d_internal
->getSygusType().toType();
459 Expr
Datatype::getSygusVarList() const {
460 return d_internal
->getSygusVarList().toExpr();
463 bool Datatype::getSygusAllowConst() const {
464 return d_internal
->getSygusAllowConst();
467 bool Datatype::getSygusAllowAll() const {
468 return d_internal
->getSygusAllowAll();
471 bool Datatype::involvesExternalType() const{
472 return d_internal
->involvesExternalType();
475 bool Datatype::involvesUninterpretedType() const{
476 return d_internal
->involvesUninterpretedType();
479 const std::vector
<DatatypeConstructor
>* Datatype::getConstructors() const
481 return &d_constructors
;
484 DatatypeConstructor::DatatypeConstructor(std::string name
)
485 : d_internal(nullptr),
486 d_testerName("is_" + name
) // default tester name is "is_FOO"
488 PrettyCheckArgument(name
!= "", name
, "cannot construct a datatype constructor without a name");
489 d_internal
= std::make_shared
<DTypeConstructor
>(name
, 1);
492 DatatypeConstructor::DatatypeConstructor(std::string name
,
495 : d_internal(nullptr), d_testerName(tester
)
497 PrettyCheckArgument(name
!= "", name
, "cannot construct a datatype constructor without a name");
498 PrettyCheckArgument(!tester
.empty(), tester
, "cannot construct a datatype constructor without a tester");
499 d_internal
= std::make_shared
<DTypeConstructor
>(name
, weight
);
502 void DatatypeConstructor::setSygus(Expr op
,
503 std::shared_ptr
<SygusPrintCallback
> spc
)
506 !isResolved(), this, "cannot modify a finalized Datatype constructor");
507 Node opn
= Node::fromExpr(op
);
508 d_internal
->setSygus(op
);
509 // print callback lives at the expression level currently
513 const std::vector
<DatatypeConstructorArg
>* DatatypeConstructor::getArgs()
519 void DatatypeConstructor::addArg(std::string selectorName
, Type selectorType
) {
520 // We don't want to introduce a new data member, because eventually
521 // we're going to be a constant stuffed inside a node. So we stow
522 // the selector type away inside a var until resolution (when we can
523 // create the proper selector type)
524 PrettyCheckArgument(!isResolved(), this, "cannot modify a finalized Datatype constructor");
525 PrettyCheckArgument(!selectorType
.isNull(), selectorType
, "cannot add a null selector type");
527 // we're using some internals, so we have to set up this library context
528 ExprManagerScope
ems(selectorType
);
530 Expr type
= NodeManager::currentNM()->mkSkolem("unresolved_" + selectorName
, TypeNode::fromType(selectorType
), "is an unresolved selector type placeholder", NodeManager::SKOLEM_EXACT_NAME
| NodeManager::SKOLEM_NO_NOTIFY
).toExpr();
531 Debug("datatypes") << type
<< endl
;
532 d_args
.push_back(DatatypeConstructorArg(selectorName
, type
));
533 d_internal
->addArg(d_args
.back().d_internal
);
536 void DatatypeConstructor::addArg(std::string selectorName
, DatatypeUnresolvedType selectorType
) {
537 // We don't want to introduce a new data member, because eventually
538 // we're going to be a constant stuffed inside a node. So we stow
539 // the selector type away after a NUL in the name string until
540 // resolution (when we can create the proper selector type)
541 PrettyCheckArgument(!isResolved(), this, "cannot modify a finalized Datatype constructor");
542 PrettyCheckArgument(selectorType
.getName() != "", selectorType
, "cannot add a null selector type");
543 d_args
.push_back(DatatypeConstructorArg(selectorName
+ '\0' + selectorType
.getName(), Expr()));
544 d_internal
->addArg(d_args
.back().d_internal
);
547 void DatatypeConstructor::addArg(std::string selectorName
, DatatypeSelfType
) {
548 // We don't want to introduce a new data member, because eventually
549 // we're going to be a constant stuffed inside a node. So we mark
550 // the name string with a NUL to indicate that we have a
551 // self-selecting selector until resolution (when we can create the
552 // proper selector type)
553 PrettyCheckArgument(!isResolved(), this, "cannot modify a finalized Datatype constructor");
554 d_args
.push_back(DatatypeConstructorArg(selectorName
+ '\0', Expr()));
555 d_internal
->addArg(d_args
.back().d_internal
);
558 std::string
DatatypeConstructor::getName() const
560 return d_internal
->getName();
563 std::string
DatatypeConstructor::getTesterName() const
565 // not stored internally, since tester names only pertain to parsing
569 Expr
DatatypeConstructor::getConstructor() const {
570 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
571 return d_constructor
;
574 Type
DatatypeConstructor::getSpecializedConstructorType(Type returnType
) const {
575 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
576 PrettyCheckArgument(returnType
.isDatatype(), this, "cannot get specialized constructor type for non-datatype type");
577 ExprManagerScope
ems(d_constructor
);
578 TypeNode tn
= TypeNode::fromType(returnType
);
579 return d_internal
->getSpecializedConstructorType(tn
).toType();
582 Expr
DatatypeConstructor::getTester() const {
583 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
584 ExprManagerScope
ems(d_constructor
);
585 return d_internal
->getTester().toExpr();
588 Expr
DatatypeConstructor::getSygusOp() const {
589 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
590 ExprManagerScope
ems(d_constructor
);
591 return d_internal
->getSygusOp().toExpr();
594 bool DatatypeConstructor::isSygusIdFunc() const {
595 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
596 ExprManagerScope
ems(d_constructor
);
597 return d_internal
->isSygusIdFunc();
600 unsigned DatatypeConstructor::getWeight() const
603 isResolved(), this, "this datatype constructor is not yet resolved");
604 ExprManagerScope
ems(d_constructor
);
605 return d_internal
->getWeight();
608 std::shared_ptr
<SygusPrintCallback
> DatatypeConstructor::getSygusPrintCallback() const
611 isResolved(), this, "this datatype constructor is not yet resolved");
615 Cardinality
DatatypeConstructor::getCardinality(Type t
) const
617 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
618 ExprManagerScope
ems(d_constructor
);
619 TypeNode tn
= TypeNode::fromType(t
);
620 return d_internal
->getCardinality(tn
);
623 bool DatatypeConstructor::isFinite(Type t
) const
625 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
626 ExprManagerScope
ems(d_constructor
);
627 TypeNode tn
= TypeNode::fromType(t
);
628 return d_internal
->isFinite(tn
);
631 bool DatatypeConstructor::isInterpretedFinite(Type t
) const
633 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
634 ExprManagerScope
ems(d_constructor
);
635 TypeNode tn
= TypeNode::fromType(t
);
636 return d_internal
->isInterpretedFinite(tn
);
639 const DatatypeConstructorArg
& DatatypeConstructor::operator[](size_t index
) const {
640 PrettyCheckArgument(index
< getNumArgs(), index
, "index out of bounds");
641 return d_args
[index
];
644 const DatatypeConstructorArg
& DatatypeConstructor::operator[](std::string name
) const {
645 for(const_iterator i
= begin(); i
!= end(); ++i
) {
646 if((*i
).getName() == name
) {
650 std::string dname
= getName();
651 IllegalArgument(name
,
652 "No such arg `%s' of constructor `%s'",
657 Expr
DatatypeConstructor::getSelector(std::string name
) const {
658 return (*this)[name
].d_selector
;
661 Type
DatatypeConstructor::getArgType(unsigned index
) const
663 PrettyCheckArgument(index
< getNumArgs(), index
, "index out of bounds");
664 ExprManagerScope
ems(d_constructor
);
665 return d_internal
->getArgType(index
).toType();
668 bool DatatypeConstructor::involvesExternalType() const{
669 ExprManagerScope
ems(d_constructor
);
670 return d_internal
->involvesExternalType();
673 bool DatatypeConstructor::involvesUninterpretedType() const{
674 ExprManagerScope
ems(d_constructor
);
675 return d_internal
->involvesUninterpretedType();
678 DatatypeConstructorArg::DatatypeConstructorArg(std::string name
, Expr selector
)
679 : d_internal(nullptr)
681 PrettyCheckArgument(name
!= "", name
, "cannot construct a datatype constructor arg without a name");
682 d_internal
= std::make_shared
<DTypeSelector
>(name
, Node::fromExpr(selector
));
685 std::string
DatatypeConstructorArg::getName() const
687 string name
= d_internal
->getName();
688 const size_t nul
= name
.find('\0');
689 if(nul
!= string::npos
) {
695 Expr
DatatypeConstructorArg::getSelector() const {
696 PrettyCheckArgument(isResolved(), this, "cannot get a selector for an unresolved datatype constructor");
700 Expr
DatatypeConstructor::getSelectorInternal( Type domainType
, size_t index
) const {
701 PrettyCheckArgument(isResolved(), this, "cannot get an internal selector for an unresolved datatype constructor");
702 PrettyCheckArgument(index
< getNumArgs(), index
, "index out of bounds");
703 ExprManagerScope
ems(d_constructor
);
704 TypeNode dtn
= TypeNode::fromType(domainType
);
705 return d_internal
->getSelectorInternal(dtn
, index
).toExpr();
708 int DatatypeConstructor::getSelectorIndexInternal( Expr sel
) const {
709 PrettyCheckArgument(isResolved(), this, "cannot get an internal selector index for an unresolved datatype constructor");
710 ExprManagerScope
ems(d_constructor
);
711 Node seln
= Node::fromExpr(sel
);
712 return d_internal
->getSelectorIndexInternal(seln
);
715 Expr
DatatypeConstructorArg::getConstructor() const {
716 PrettyCheckArgument(isResolved(), this,
717 "cannot get a associated constructor for argument of an unresolved datatype constructor");
718 ExprManagerScope
ems(d_selector
);
719 return d_internal
->getConstructor().toExpr();
722 SelectorType
DatatypeConstructorArg::getType() const {
723 return d_selector
.getType();
726 Type
DatatypeConstructorArg::getRangeType() const {
727 return getType().getRangeType();
730 bool DatatypeConstructorArg::isUnresolvedSelf() const
732 return d_selector
.isNull();
735 bool DatatypeConstructorArg::isResolved() const
737 // We could just write:
739 // return !d_selector.isNull() && d_selector.getType().isSelector();
741 // HOWEVER, this causes problems in ExprManager tear-down, because
742 // the attributes are removed before the pool is purged. When the
743 // pool is purged, this triggers an equality test between Datatypes,
744 // and this triggers a call to isResolved(), which breaks because
745 // d_selector has no type after attributes are stripped.
747 // This problem, coupled with the fact that this function is called
748 // _often_, means we should just use a boolean flag.
750 return d_internal
->isResolved();
753 std::ostream
& operator<<(std::ostream
& os
, const Datatype
& dt
)
755 // can only output datatypes in the CVC4 native language
756 language::SetLanguage::Scope
ls(os
, language::output::LANG_CVC4
);
761 void Datatype::toStream(std::ostream
& out
) const
763 out
<< "DATATYPE " << getName();
767 for (size_t i
= 0; i
< getNumParameters(); ++i
)
772 out
<< getParameter(i
);
777 Datatype::const_iterator i
= begin(), i_end
= end();
787 out
<< "END;" << endl
;
790 std::ostream
& operator<<(std::ostream
& os
, const DatatypeConstructor
& ctor
) {
791 // can only output datatypes in the CVC4 native language
792 language::SetLanguage::Scope
ls(os
, language::output::LANG_CVC4
);
797 void DatatypeConstructor::toStream(std::ostream
& out
) const
801 DatatypeConstructor::const_iterator i
= begin(), i_end
= end();
814 std::ostream
& operator<<(std::ostream
& os
, const DatatypeConstructorArg
& arg
) {
815 // can only output datatypes in the CVC4 native language
816 language::SetLanguage::Scope
ls(os
, language::output::LANG_CVC4
);
821 void DatatypeConstructorArg::toStream(std::ostream
& out
) const
823 std::string name
= getName();
831 else if (d_selector
.isNull())
833 string typeName
= name
.substr(name
.find('\0') + 1);
834 out
<< ((typeName
== "") ? "[self]" : typeName
);
839 t
= d_selector
.getType();
844 DatatypeIndexConstant::DatatypeIndexConstant(unsigned index
) : d_index(index
) {}
845 std::ostream
& operator<<(std::ostream
& out
, const DatatypeIndexConstant
& dic
) {
846 return out
<< "index_" << dic
.getIndex();
850 std::string
Datatype::getName() const
852 ExprManagerScope
ems(*d_em
);
853 return d_internal
->getName();
855 size_t Datatype::getNumConstructors() const { return d_constructors
.size(); }
857 bool Datatype::isParametric() const
859 ExprManagerScope
ems(*d_em
);
860 return d_internal
->isParametric();
862 size_t Datatype::getNumParameters() const
864 ExprManagerScope
ems(*d_em
);
865 return d_internal
->getNumParameters();
867 Type
Datatype::getParameter(unsigned int i
) const
869 CheckArgument(isParametric(),
871 "Cannot get type parameter of a non-parametric datatype.");
872 CheckArgument(i
< getNumParameters(),
874 "Type parameter index out of range for datatype.");
875 ExprManagerScope
ems(*d_em
);
876 return d_internal
->getParameter(i
).toType();
879 std::vector
<Type
> Datatype::getParameters() const
881 CheckArgument(isParametric(),
883 "Cannot get type parameters of a non-parametric datatype.");
884 std::vector
<Type
> params
;
885 std::vector
<TypeNode
> paramsn
= d_internal
->getParameters();
887 for (unsigned i
= 0, nparams
= paramsn
.size(); i
< nparams
; i
++)
889 params
.push_back(paramsn
[i
].toType());
894 bool Datatype::isCodatatype() const
896 ExprManagerScope
ems(*d_em
);
897 return d_internal
->isCodatatype();
900 bool Datatype::isSygus() const
902 ExprManagerScope
ems(*d_em
);
903 return d_internal
->isSygus();
906 bool Datatype::isTuple() const
908 ExprManagerScope
ems(*d_em
);
909 return d_internal
->isTuple();
912 bool Datatype::isRecord() const { return d_isRecord
; }
914 Record
* Datatype::getRecord() const { return d_record
; }
915 bool Datatype::operator!=(const Datatype
& other
) const
917 return !(*this == other
);
920 bool Datatype::isResolved() const
922 ExprManagerScope
ems(*d_em
);
923 return d_internal
->isResolved();
925 Datatype::iterator
Datatype::begin() { return iterator(d_constructors
, true); }
927 Datatype::iterator
Datatype::end() { return iterator(d_constructors
, false); }
929 Datatype::const_iterator
Datatype::begin() const
931 return const_iterator(d_constructors
, true);
934 Datatype::const_iterator
Datatype::end() const
936 return const_iterator(d_constructors
, false);
939 bool DatatypeConstructor::isResolved() const
941 return d_internal
->isResolved();
944 size_t DatatypeConstructor::getNumArgs() const { return d_args
.size(); }
946 DatatypeConstructor::iterator
DatatypeConstructor::begin()
948 return iterator(d_args
, true);
951 DatatypeConstructor::iterator
DatatypeConstructor::end()
953 return iterator(d_args
, false);
956 DatatypeConstructor::const_iterator
DatatypeConstructor::begin() const
958 return const_iterator(d_args
, true);
961 DatatypeConstructor::const_iterator
DatatypeConstructor::end() const
963 return const_iterator(d_args
, false);
965 }/* CVC4 namespace */