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::setTuple() {
258 !isResolved(), this, "cannot set tuple to a finalized Datatype");
259 d_internal
->setTuple();
262 void Datatype::setRecord() {
264 !isResolved(), this, "cannot set record to a finalized Datatype");
268 Cardinality
Datatype::getCardinality(Type t
) const
270 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
271 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
272 ExprManagerScope
ems(d_self
);
273 TypeNode tn
= TypeNode::fromType(t
);
274 return d_internal
->getCardinality(tn
);
277 Cardinality
Datatype::getCardinality() const
279 PrettyCheckArgument(!isParametric(), this, "for getCardinality, this datatype cannot be parametric");
280 ExprManagerScope
ems(d_self
);
281 return d_internal
->getCardinality();
284 bool Datatype::isRecursiveSingleton(Type t
) const
286 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
287 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
288 ExprManagerScope
ems(d_self
);
289 TypeNode tn
= TypeNode::fromType(t
);
290 return d_internal
->isRecursiveSingleton(tn
);
293 bool Datatype::isRecursiveSingleton() const
295 PrettyCheckArgument(!isParametric(), this, "for isRecursiveSingleton, this datatype cannot be parametric");
296 ExprManagerScope
ems(d_self
);
297 return d_internal
->isRecursiveSingleton();
300 unsigned Datatype::getNumRecursiveSingletonArgTypes(Type t
) const
302 Assert(isRecursiveSingleton(t
));
303 ExprManagerScope
ems(d_self
);
304 TypeNode tn
= TypeNode::fromType(t
);
305 return d_internal
->getNumRecursiveSingletonArgTypes(tn
);
308 unsigned Datatype::getNumRecursiveSingletonArgTypes() const
310 PrettyCheckArgument(!isParametric(), this, "for getNumRecursiveSingletonArgTypes, this datatype cannot be parametric");
311 ExprManagerScope
ems(d_self
);
312 return d_internal
->getNumRecursiveSingletonArgTypes();
315 Type
Datatype::getRecursiveSingletonArgType(Type t
, unsigned i
) const
317 Assert(isRecursiveSingleton(t
));
318 ExprManagerScope
ems(d_self
);
319 TypeNode tn
= TypeNode::fromType(t
);
320 return d_internal
->getRecursiveSingletonArgType(tn
, i
).toType();
323 Type
Datatype::getRecursiveSingletonArgType(unsigned i
) const
325 PrettyCheckArgument(!isParametric(), this, "for getRecursiveSingletonArgType, this datatype cannot be parametric");
326 ExprManagerScope
ems(d_self
);
327 return d_internal
->getRecursiveSingletonArgType(i
).toType();
330 bool Datatype::isFinite(Type t
) const
332 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
333 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
334 ExprManagerScope
ems(d_self
);
335 TypeNode tn
= TypeNode::fromType(t
);
336 return d_internal
->isFinite(tn
);
338 bool Datatype::isFinite() const
340 PrettyCheckArgument(isResolved() && !isParametric(), this, "this datatype must be resolved and not parametric");
341 ExprManagerScope
ems(d_self
);
342 return d_internal
->isFinite();
345 bool Datatype::isInterpretedFinite(Type t
) const
347 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
348 Assert(t
.isDatatype() && ((DatatypeType
)t
).getDatatype() == *this);
349 ExprManagerScope
ems(d_self
);
350 TypeNode tn
= TypeNode::fromType(t
);
351 return d_internal
->isInterpretedFinite(tn
);
353 bool Datatype::isInterpretedFinite() const
355 PrettyCheckArgument(isResolved() && !isParametric(), this, "this datatype must be resolved and not parametric");
356 ExprManagerScope
ems(d_self
);
357 return d_internal
->isInterpretedFinite();
360 bool Datatype::isWellFounded() const
362 ExprManagerScope
ems(d_self
);
363 return d_internal
->isWellFounded();
366 Expr
Datatype::mkGroundTerm(Type t
) const
368 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
369 ExprManagerScope
ems(d_self
);
370 TypeNode tn
= TypeNode::fromType(t
);
371 Node gterm
= d_internal
->mkGroundTerm(tn
);
375 "datatype is not well-founded, cannot construct a ground term!");
376 return gterm
.toExpr();
379 Expr
Datatype::mkGroundValue(Type t
) const
381 PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
382 ExprManagerScope
ems(d_self
);
383 TypeNode tn
= TypeNode::fromType(t
);
384 Node gvalue
= d_internal
->mkGroundValue(tn
);
388 "datatype is not well-founded, cannot construct a ground value!");
389 return gvalue
.toExpr();
392 DatatypeType
Datatype::getDatatypeType() const
394 PrettyCheckArgument(isResolved(), *this, "Datatype must be resolved to get its DatatypeType");
395 ExprManagerScope
ems(d_self
);
396 Type self
= d_internal
->getTypeNode().toType();
397 PrettyCheckArgument(!self
.isNull(), *this);
398 return DatatypeType(self
);
401 DatatypeType
Datatype::getDatatypeType(const std::vector
<Type
>& params
) const
403 PrettyCheckArgument(isResolved(), *this, "Datatype must be resolved to get its DatatypeType");
404 ExprManagerScope
ems(d_self
);
405 Type self
= d_internal
->getTypeNode().toType();
406 PrettyCheckArgument(!self
.isNull() && DatatypeType(self
).isParametric(),
408 return DatatypeType(self
).instantiate(params
);
411 bool Datatype::operator==(const Datatype
& other
) const
413 // two datatypes are == iff the name is the same and they have
414 // exactly matching constructors (in the same order)
422 const DatatypeConstructor
& Datatype::operator[](size_t index
) const {
423 PrettyCheckArgument(index
< getNumConstructors(), index
, "index out of bounds");
424 return d_constructors
[index
];
427 const DatatypeConstructor
& Datatype::operator[](std::string name
) const {
428 for(const_iterator i
= begin(); i
!= end(); ++i
) {
429 if((*i
).getName() == name
) {
433 std::string dname
= getName();
434 IllegalArgument(name
,
435 "No such constructor `%s' of datatype `%s'",
440 Expr
Datatype::getConstructor(std::string name
) const {
441 return (*this)[name
].getConstructor();
444 Type
Datatype::getSygusType() const {
445 return d_internal
->getSygusType().toType();
448 Expr
Datatype::getSygusVarList() const {
449 return d_internal
->getSygusVarList().toExpr();
452 bool Datatype::getSygusAllowConst() const {
453 return d_internal
->getSygusAllowConst();
456 bool Datatype::getSygusAllowAll() const {
457 return d_internal
->getSygusAllowAll();
460 bool Datatype::involvesExternalType() const{
461 return d_internal
->involvesExternalType();
464 bool Datatype::involvesUninterpretedType() const{
465 return d_internal
->involvesUninterpretedType();
468 const std::vector
<DatatypeConstructor
>* Datatype::getConstructors() const
470 return &d_constructors
;
473 DatatypeConstructor::DatatypeConstructor(std::string name
)
474 : d_internal(nullptr),
475 d_testerName("is_" + name
) // default tester name is "is_FOO"
477 PrettyCheckArgument(name
!= "", name
, "cannot construct a datatype constructor without a name");
478 d_internal
= std::make_shared
<DTypeConstructor
>(name
, 1);
481 DatatypeConstructor::DatatypeConstructor(std::string name
,
484 : d_internal(nullptr), d_testerName(tester
)
486 PrettyCheckArgument(name
!= "", name
, "cannot construct a datatype constructor without a name");
487 PrettyCheckArgument(!tester
.empty(), tester
, "cannot construct a datatype constructor without a tester");
488 d_internal
= std::make_shared
<DTypeConstructor
>(name
, weight
);
491 void DatatypeConstructor::setSygus(Expr op
,
492 std::shared_ptr
<SygusPrintCallback
> spc
)
495 !isResolved(), this, "cannot modify a finalized Datatype constructor");
496 Node opn
= Node::fromExpr(op
);
497 d_internal
->setSygus(op
);
498 // print callback lives at the expression level currently
502 const std::vector
<DatatypeConstructorArg
>* DatatypeConstructor::getArgs()
508 void DatatypeConstructor::addArg(std::string selectorName
, Type selectorType
) {
509 // We don't want to introduce a new data member, because eventually
510 // we're going to be a constant stuffed inside a node. So we stow
511 // the selector type away inside a var until resolution (when we can
512 // create the proper selector type)
513 PrettyCheckArgument(!isResolved(), this, "cannot modify a finalized Datatype constructor");
514 PrettyCheckArgument(!selectorType
.isNull(), selectorType
, "cannot add a null selector type");
516 // we're using some internals, so we have to set up this library context
517 ExprManagerScope
ems(selectorType
);
519 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();
520 Debug("datatypes") << type
<< endl
;
521 d_args
.push_back(DatatypeConstructorArg(selectorName
, type
));
522 d_internal
->addArg(d_args
.back().d_internal
);
525 void DatatypeConstructor::addArg(std::string selectorName
, DatatypeUnresolvedType selectorType
) {
526 // We don't want to introduce a new data member, because eventually
527 // we're going to be a constant stuffed inside a node. So we stow
528 // the selector type away after a NUL in the name string until
529 // resolution (when we can create the proper selector type)
530 PrettyCheckArgument(!isResolved(), this, "cannot modify a finalized Datatype constructor");
531 PrettyCheckArgument(selectorType
.getName() != "", selectorType
, "cannot add a null selector type");
532 d_args
.push_back(DatatypeConstructorArg(selectorName
+ '\0' + selectorType
.getName(), Expr()));
533 d_internal
->addArg(d_args
.back().d_internal
);
536 void DatatypeConstructor::addArg(std::string selectorName
, DatatypeSelfType
) {
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 mark
539 // the name string with a NUL to indicate that we have a
540 // self-selecting selector until resolution (when we can create the
541 // proper selector type)
542 PrettyCheckArgument(!isResolved(), this, "cannot modify a finalized Datatype constructor");
543 d_args
.push_back(DatatypeConstructorArg(selectorName
+ '\0', Expr()));
544 d_internal
->addArg(d_args
.back().d_internal
);
547 std::string
DatatypeConstructor::getName() const
549 return d_internal
->getName();
552 std::string
DatatypeConstructor::getTesterName() const
554 // not stored internally, since tester names only pertain to parsing
558 Expr
DatatypeConstructor::getConstructor() const {
559 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
560 return d_constructor
;
563 Type
DatatypeConstructor::getSpecializedConstructorType(Type returnType
) const {
564 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
565 PrettyCheckArgument(returnType
.isDatatype(), this, "cannot get specialized constructor type for non-datatype type");
566 ExprManagerScope
ems(d_constructor
);
567 TypeNode tn
= TypeNode::fromType(returnType
);
568 return d_internal
->getSpecializedConstructorType(tn
).toType();
571 Expr
DatatypeConstructor::getTester() const {
572 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
573 ExprManagerScope
ems(d_constructor
);
574 return d_internal
->getTester().toExpr();
577 Expr
DatatypeConstructor::getSygusOp() const {
578 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
579 ExprManagerScope
ems(d_constructor
);
580 return d_internal
->getSygusOp().toExpr();
583 bool DatatypeConstructor::isSygusIdFunc() const {
584 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
585 ExprManagerScope
ems(d_constructor
);
586 return d_internal
->isSygusIdFunc();
589 unsigned DatatypeConstructor::getWeight() const
592 isResolved(), this, "this datatype constructor is not yet resolved");
593 ExprManagerScope
ems(d_constructor
);
594 return d_internal
->getWeight();
597 std::shared_ptr
<SygusPrintCallback
> DatatypeConstructor::getSygusPrintCallback() const
600 isResolved(), this, "this datatype constructor is not yet resolved");
604 Cardinality
DatatypeConstructor::getCardinality(Type t
) const
606 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
607 ExprManagerScope
ems(d_constructor
);
608 TypeNode tn
= TypeNode::fromType(t
);
609 return d_internal
->getCardinality(tn
);
612 bool DatatypeConstructor::isFinite(Type t
) const
614 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
615 ExprManagerScope
ems(d_constructor
);
616 TypeNode tn
= TypeNode::fromType(t
);
617 return d_internal
->isFinite(tn
);
620 bool DatatypeConstructor::isInterpretedFinite(Type t
) const
622 PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
623 ExprManagerScope
ems(d_constructor
);
624 TypeNode tn
= TypeNode::fromType(t
);
625 return d_internal
->isInterpretedFinite(tn
);
628 const DatatypeConstructorArg
& DatatypeConstructor::operator[](size_t index
) const {
629 PrettyCheckArgument(index
< getNumArgs(), index
, "index out of bounds");
630 return d_args
[index
];
633 const DatatypeConstructorArg
& DatatypeConstructor::operator[](std::string name
) const {
634 for(const_iterator i
= begin(); i
!= end(); ++i
) {
635 if((*i
).getName() == name
) {
639 std::string dname
= getName();
640 IllegalArgument(name
,
641 "No such arg `%s' of constructor `%s'",
646 Expr
DatatypeConstructor::getSelector(std::string name
) const {
647 return (*this)[name
].d_selector
;
650 Type
DatatypeConstructor::getArgType(unsigned index
) const
652 PrettyCheckArgument(index
< getNumArgs(), index
, "index out of bounds");
653 ExprManagerScope
ems(d_constructor
);
654 return d_internal
->getArgType(index
).toType();
657 bool DatatypeConstructor::involvesExternalType() const{
658 ExprManagerScope
ems(d_constructor
);
659 return d_internal
->involvesExternalType();
662 bool DatatypeConstructor::involvesUninterpretedType() const{
663 ExprManagerScope
ems(d_constructor
);
664 return d_internal
->involvesUninterpretedType();
667 DatatypeConstructorArg::DatatypeConstructorArg(std::string name
, Expr selector
)
668 : d_internal(nullptr)
670 PrettyCheckArgument(name
!= "", name
, "cannot construct a datatype constructor arg without a name");
671 d_internal
= std::make_shared
<DTypeSelector
>(name
, Node::fromExpr(selector
));
674 std::string
DatatypeConstructorArg::getName() const
676 string name
= d_internal
->getName();
677 const size_t nul
= name
.find('\0');
678 if(nul
!= string::npos
) {
684 Expr
DatatypeConstructorArg::getSelector() const {
685 PrettyCheckArgument(isResolved(), this, "cannot get a selector for an unresolved datatype constructor");
689 Expr
DatatypeConstructor::getSelectorInternal( Type domainType
, size_t index
) const {
690 PrettyCheckArgument(isResolved(), this, "cannot get an internal selector for an unresolved datatype constructor");
691 PrettyCheckArgument(index
< getNumArgs(), index
, "index out of bounds");
692 ExprManagerScope
ems(d_constructor
);
693 TypeNode dtn
= TypeNode::fromType(domainType
);
694 return d_internal
->getSelectorInternal(dtn
, index
).toExpr();
697 int DatatypeConstructor::getSelectorIndexInternal( Expr sel
) const {
698 PrettyCheckArgument(isResolved(), this, "cannot get an internal selector index for an unresolved datatype constructor");
699 ExprManagerScope
ems(d_constructor
);
700 Node seln
= Node::fromExpr(sel
);
701 return d_internal
->getSelectorIndexInternal(seln
);
704 Expr
DatatypeConstructorArg::getConstructor() const {
705 PrettyCheckArgument(isResolved(), this,
706 "cannot get a associated constructor for argument of an unresolved datatype constructor");
707 ExprManagerScope
ems(d_selector
);
708 return d_internal
->getConstructor().toExpr();
711 SelectorType
DatatypeConstructorArg::getType() const {
712 return d_selector
.getType();
715 Type
DatatypeConstructorArg::getRangeType() const {
716 return getType().getRangeType();
719 bool DatatypeConstructorArg::isUnresolvedSelf() const
721 return d_selector
.isNull();
724 bool DatatypeConstructorArg::isResolved() const
726 // We could just write:
728 // return !d_selector.isNull() && d_selector.getType().isSelector();
730 // HOWEVER, this causes problems in ExprManager tear-down, because
731 // the attributes are removed before the pool is purged. When the
732 // pool is purged, this triggers an equality test between Datatypes,
733 // and this triggers a call to isResolved(), which breaks because
734 // d_selector has no type after attributes are stripped.
736 // This problem, coupled with the fact that this function is called
737 // _often_, means we should just use a boolean flag.
739 return d_internal
->isResolved();
742 std::ostream
& operator<<(std::ostream
& os
, const Datatype
& dt
)
744 // can only output datatypes in the CVC4 native language
745 language::SetLanguage::Scope
ls(os
, language::output::LANG_CVC4
);
750 void Datatype::toStream(std::ostream
& out
) const
752 out
<< "DATATYPE " << getName();
756 for (size_t i
= 0; i
< getNumParameters(); ++i
)
761 out
<< getParameter(i
);
766 Datatype::const_iterator i
= begin(), i_end
= end();
776 out
<< "END;" << endl
;
779 std::ostream
& operator<<(std::ostream
& os
, const DatatypeConstructor
& ctor
) {
780 // can only output datatypes in the CVC4 native language
781 language::SetLanguage::Scope
ls(os
, language::output::LANG_CVC4
);
786 void DatatypeConstructor::toStream(std::ostream
& out
) const
790 DatatypeConstructor::const_iterator i
= begin(), i_end
= end();
803 std::ostream
& operator<<(std::ostream
& os
, const DatatypeConstructorArg
& arg
) {
804 // can only output datatypes in the CVC4 native language
805 language::SetLanguage::Scope
ls(os
, language::output::LANG_CVC4
);
810 void DatatypeConstructorArg::toStream(std::ostream
& out
) const
812 std::string name
= getName();
820 else if (d_selector
.isNull())
822 string typeName
= name
.substr(name
.find('\0') + 1);
823 out
<< ((typeName
== "") ? "[self]" : typeName
);
828 t
= d_selector
.getType();
833 DatatypeIndexConstant::DatatypeIndexConstant(unsigned index
) : d_index(index
) {}
834 std::ostream
& operator<<(std::ostream
& out
, const DatatypeIndexConstant
& dic
) {
835 return out
<< "index_" << dic
.getIndex();
839 std::string
Datatype::getName() const
841 ExprManagerScope
ems(*d_em
);
842 return d_internal
->getName();
844 size_t Datatype::getNumConstructors() const { return d_constructors
.size(); }
846 bool Datatype::isParametric() const
848 ExprManagerScope
ems(*d_em
);
849 return d_internal
->isParametric();
851 size_t Datatype::getNumParameters() const
853 ExprManagerScope
ems(*d_em
);
854 return d_internal
->getNumParameters();
856 Type
Datatype::getParameter(unsigned int i
) const
858 CheckArgument(isParametric(),
860 "Cannot get type parameter of a non-parametric datatype.");
861 CheckArgument(i
< getNumParameters(),
863 "Type parameter index out of range for datatype.");
864 ExprManagerScope
ems(*d_em
);
865 return d_internal
->getParameter(i
).toType();
868 std::vector
<Type
> Datatype::getParameters() const
870 CheckArgument(isParametric(),
872 "Cannot get type parameters of a non-parametric datatype.");
873 std::vector
<Type
> params
;
874 std::vector
<TypeNode
> paramsn
= d_internal
->getParameters();
876 for (unsigned i
= 0, nparams
= paramsn
.size(); i
< nparams
; i
++)
878 params
.push_back(paramsn
[i
].toType());
883 bool Datatype::isCodatatype() const
885 ExprManagerScope
ems(*d_em
);
886 return d_internal
->isCodatatype();
889 bool Datatype::isSygus() const
891 ExprManagerScope
ems(*d_em
);
892 return d_internal
->isSygus();
895 bool Datatype::isTuple() const
897 ExprManagerScope
ems(*d_em
);
898 return d_internal
->isTuple();
901 bool Datatype::isRecord() const { return d_isRecord
; }
903 Record
* Datatype::getRecord() const { return d_record
; }
904 bool Datatype::operator!=(const Datatype
& other
) const
906 return !(*this == other
);
909 bool Datatype::isResolved() const
911 ExprManagerScope
ems(*d_em
);
912 return d_internal
->isResolved();
914 Datatype::iterator
Datatype::begin() { return iterator(d_constructors
, true); }
916 Datatype::iterator
Datatype::end() { return iterator(d_constructors
, false); }
918 Datatype::const_iterator
Datatype::begin() const
920 return const_iterator(d_constructors
, true);
923 Datatype::const_iterator
Datatype::end() const
925 return const_iterator(d_constructors
, false);
928 bool DatatypeConstructor::isResolved() const
930 return d_internal
->isResolved();
933 size_t DatatypeConstructor::getNumArgs() const { return d_args
.size(); }
935 DatatypeConstructor::iterator
DatatypeConstructor::begin()
937 return iterator(d_args
, true);
940 DatatypeConstructor::iterator
DatatypeConstructor::end()
942 return iterator(d_args
, false);
945 DatatypeConstructor::const_iterator
DatatypeConstructor::begin() const
947 return const_iterator(d_args
, true);
950 DatatypeConstructor::const_iterator
DatatypeConstructor::end() const
952 return const_iterator(d_args
, false);
954 }/* CVC4 namespace */