1 /********************* */
2 /*! \file theory_datatypes_utils.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Morgan Deters, Mathias Preiner
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 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 Implementation of rewriter for the theory of (co)inductive datatypes.
14 ** Implementation of rewriter for the theory of (co)inductive datatypes.
17 #include "theory/datatypes/theory_datatypes_utils.h"
19 #include "expr/dtype.h"
22 using namespace CVC4::kind
;
29 /** get instantiate cons */
30 Node
getInstCons(Node n
, const DType
& dt
, int index
)
32 Assert(index
>= 0 && index
< (int)dt
.getNumConstructors());
33 std::vector
<Node
> children
;
34 NodeManager
* nm
= NodeManager::currentNM();
35 children
.push_back(dt
[index
].getConstructor());
36 TypeNode tn
= n
.getType();
37 for (unsigned i
= 0, nargs
= dt
[index
].getNumArgs(); i
< nargs
; i
++)
40 APPLY_SELECTOR_TOTAL
, dt
[index
].getSelectorInternal(tn
, i
), n
);
41 children
.push_back(nc
);
43 Node n_ic
= nm
->mkNode(APPLY_CONSTRUCTOR
, children
);
44 if (dt
.isParametric())
46 // add type ascription for ambiguous constructor types
47 if (!n_ic
.getType().isComparableTo(tn
))
49 Debug("datatypes-parametric")
50 << "DtInstantiate: ambiguous type for " << n_ic
<< ", ascribe to "
51 << n
.getType() << std::endl
;
52 Debug("datatypes-parametric")
53 << "Constructor is " << dt
[index
] << std::endl
;
54 TypeNode tspec
= dt
[index
].getSpecializedConstructorType(n
.getType());
55 Debug("datatypes-parametric")
56 << "Type specification is " << tspec
<< std::endl
;
57 children
[0] = nm
->mkNode(APPLY_TYPE_ASCRIPTION
,
58 nm
->mkConst(AscriptionType(tspec
)),
60 n_ic
= nm
->mkNode(APPLY_CONSTRUCTOR
, children
);
61 Assert(n_ic
.getType() == tn
);
64 Assert(isInstCons(n
, n_ic
, dt
) == index
);
65 // n_ic = Rewriter::rewrite( n_ic );
69 int isInstCons(Node t
, Node n
, const DType
& dt
)
71 if (n
.getKind() == APPLY_CONSTRUCTOR
)
73 int index
= indexOf(n
.getOperator());
74 const DTypeConstructor
& c
= dt
[index
];
75 TypeNode tn
= n
.getType();
76 for (unsigned i
= 0, size
= n
.getNumChildren(); i
< size
; i
++)
78 if (n
[i
].getKind() != APPLY_SELECTOR_TOTAL
79 || n
[i
].getOperator() != c
.getSelectorInternal(tn
, i
) || n
[i
][0] != t
)
89 int isTester(Node n
, Node
& a
)
91 if (n
.getKind() == APPLY_TESTER
)
94 return indexOf(n
.getOperator());
101 if (n
.getKind() == APPLY_TESTER
)
103 return indexOf(n
.getOperator());
108 size_t indexOf(Node n
) { return DType::indexOf(n
); }
110 size_t cindexOf(Node n
) { return DType::cindexOf(n
); }
112 const DType
& datatypeOf(Node n
)
114 TypeNode t
= n
.getType();
117 case CONSTRUCTOR_TYPE
: return t
[t
.getNumChildren() - 1].getDType();
119 case TESTER_TYPE
: return t
[0].getDType();
121 Unhandled() << "arg must be a datatype constructor, selector, or tester";
125 Node
mkTester(Node n
, int i
, const DType
& dt
)
127 return NodeManager::currentNM()->mkNode(APPLY_TESTER
, dt
[i
].getTester(), n
);
130 Node
mkSplit(Node n
, const DType
& dt
)
132 std::vector
<Node
> splits
;
133 for (unsigned i
= 0, ncons
= dt
.getNumConstructors(); i
< ncons
; i
++)
135 Node test
= mkTester(n
, i
, dt
);
136 splits
.push_back(test
);
138 NodeManager
* nm
= NodeManager::currentNM();
139 return splits
.size() == 1 ? splits
[0] : nm
->mkNode(OR
, splits
);
142 bool isNullaryApplyConstructor(Node n
)
144 Assert(n
.getKind() == APPLY_CONSTRUCTOR
);
145 for (const Node
& nc
: n
)
147 if (nc
.getType().isDatatype())
155 bool isNullaryConstructor(const DTypeConstructor
& c
)
157 for (unsigned j
= 0, nargs
= c
.getNumArgs(); j
< nargs
; j
++)
159 if (c
[j
].getType().getRangeType().isDatatype())
167 bool checkClash(Node n1
, Node n2
, std::vector
<Node
>& rew
)
169 Trace("datatypes-rewrite-debug")
170 << "Check clash : " << n1
<< " " << n2
<< std::endl
;
171 if (n1
.getKind() == APPLY_CONSTRUCTOR
&& n2
.getKind() == APPLY_CONSTRUCTOR
)
173 if (n1
.getOperator() != n2
.getOperator())
175 Trace("datatypes-rewrite-debug")
176 << "Clash operators : " << n1
<< " " << n2
<< " " << n1
.getOperator()
177 << " " << n2
.getOperator() << std::endl
;
180 Assert(n1
.getNumChildren() == n2
.getNumChildren());
181 for (unsigned i
= 0, size
= n1
.getNumChildren(); i
< size
; i
++)
183 if (checkClash(n1
[i
], n2
[i
], rew
))
191 if (n1
.isConst() && n2
.isConst())
193 Trace("datatypes-rewrite-debug")
194 << "Clash constants : " << n1
<< " " << n2
<< std::endl
;
199 Node eq
= NodeManager::currentNM()->mkNode(EQUAL
, n1
, n2
);
207 } // namespace datatypes
208 } // namespace theory