Expr e = f.getOperator();
const Datatype::Constructor& dtc = Datatype::datatypeOf(e)[Datatype::indexOf(e)];
v.push_back(MK_EXPR( CVC4::kind::APPLY_TYPE_ASCRIPTION,
- MK_CONST(AscriptionType(dtc.getSpecializedConstructorType(t))), f.getOperator()[0] ));
+ MK_CONST(AscriptionType(dtc.getSpecializedConstructorType(t))), f.getOperator() ));
v.insert(v.end(), f.begin(), f.end());
f = MK_EXPR(CVC4::kind::APPLY_CONSTRUCTOR, v);
} else {
while(!done()) {
Node assertion = get();
if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") || Debug.isOn("datatypes-cycles")
- || Debug.isOn("datatypes-debug-pf") ) {
+ || Debug.isOn("datatypes-debug-pf") || Debug.isOn("datatypes-conflict") ) {
cout << "*** TheoryDatatypes::check(): " << assertion << endl;
d_currAsserts.push_back( assertion );
}
//if there is now a conflict
if( hasConflict() ) {
Debug("datatypes-conflict") << "Constructing conflict..." << endl;
- Debug("datatypes-conflict") << d_cc << std::endl;
+ for( int i=0; i<(int)d_currAsserts.size(); i++ ) {
+ Debug("datatypes-conflict") << "currAsserts[" << i << "] = " << d_currAsserts[i] << endl;
+ }
+ //Debug("datatypes-conflict") << d_cc << std::endl;
Node conflict = d_em.getConflict();
if( Debug.isOn("datatypes") || Debug.isOn("datatypes-split") ||
Debug.isOn("datatypes-cycles") || Debug.isOn("datatypes-conflict") ){
}
if( cn.isFinite() || foundSel ) {
d_inst_map[ te ] = true;
- //instantiate, add equality
Node val = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, selectorVals );
- val = doTypeAscription( val, te.getType() ); //IDT-param
+ //instantiate, add equality
+ if( val.getType()!=te.getType() ){ //IDT-param
+ Assert( Datatype::datatypeOf( cons.toExpr() ).isParametric() );
+ Debug("datatypes-gt") << "Inst: ambiguous type for " << cons << ", ascribe to " << te.getType() << std::endl;
+ const Datatype::Constructor& dtc = Datatype::datatypeOf(cons.toExpr())[Datatype::indexOf(cons.toExpr())];
+ Debug("datatypes-gt") << "constructor is " << dtc << std::endl;
+ Type tspec = dtc.getSpecializedConstructorType(te.getType().toType());
+ Debug("datatypes-gt") << "tpec is " << tspec << std::endl;
+ selectorVals[0] = NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
+ NodeManager::currentNM()->mkConst(AscriptionType(tspec)), cons);
+ val = NodeManager::currentNM()->mkNode( APPLY_CONSTRUCTOR, selectorVals );
+ }
if( find( val ) != find( te ) ) {
//build explaination
NodeBuilder<> nb(kind::AND);
retNode = tmp[ Datatype::indexOf( sel.toExpr() ) ];
} else {
Debug("datatypes") << "Applied selector " << t << " to wrong constructor." << endl;
- retNode = doTypeAscription( retTyp.mkGroundTerm(), selType[1] ); //IDT-param
- //retNode = selType[1].mkGroundTerm();
+ retNode = retTyp.mkGroundTerm(); //IDT-param
}
if( tmp!=t[0] ){
t = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, t.getOperator(), tmp );
tester = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( cn.getTester() ), t[0] );
d_em.addNode( tester.notNode(), exp, Reason::idt_tcong );
}
- retNode = doTypeAscription( retTyp.mkGroundTerm(), retTyp ); //IDT-param
- //retNode = selType[1].mkGroundTerm();
+ retNode = retTyp.mkGroundTerm(); //IDT-param
Node neq = NodeManager::currentNM()->mkNode( EQUAL, retNode, t );
d_em.addNode( neq, tester.notNode(), Reason::idt_collapse2 );
}
return false;
}
-
-Node TheoryDatatypes::doTypeAscription( Node t, TypeNode typ )
-{
- TypeNode tt = t.getType();
- if( (tt.isDatatype() || tt.isParametricDatatype()) && !tt.isInstantiatedDatatype() ){
- return NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
- NodeManager::currentNM()->mkConst(AscriptionType(typ.toType())), t);
- }else{
- return t;
- }
-}
bool searchForCycle( Node n, Node on,
std::map< Node, bool >& visited,
NodeBuilder<>& explanation );
- Node doTypeAscription( Node t, TypeNode typ );
};/* class TheoryDatatypes */
inline bool TheoryDatatypes::hasConflict() {
TypeNode t = TypeNode::fromType(n.getOperator().getConst<AscriptionType>().getType());
if(check) {
TypeNode childType = n[0].getType(check);
- if(!t.getKind() == kind::DATATYPE_TYPE) {
- throw TypeCheckingExceptionPrivate(n, "bad type for datatype type ascription");
+ //if(!t.getKind() == kind::DATATYPE_TYPE) {
+ // throw TypeCheckingExceptionPrivate(n, "bad type for datatype type ascription");
+ //}
+ //DatatypeType dt = DatatypeType(childType.toType());
+ //if( dt.isParametric() ){
+ // Debug("typecheck-idt") << "typecheck parameterized ascription: " << n << std::endl;
+ // Matcher m( dt );
+ // if( !m.doMatching( childType, t ) ){
+ // throw TypeCheckingExceptionPrivate(n, "matching failed for type ascription argument of parameterized datatype");
+ // }
+ //}else{
+ // Debug("typecheck-idt") << "typecheck test: " << n << std::endl;
+ // if(t != childType) {
+ // throw TypeCheckingExceptionPrivate(n, "bad type for type ascription argument");
+ // }
+ //}
+
+ Matcher m;
+ if( childType.getKind() == kind::CONSTRUCTOR_TYPE ){
+ m.addTypesFromDatatype( ConstructorType(childType.toType()).getRangeType() );
+ }else if( childType.getKind() == kind::DATATYPE_TYPE ){
+ m.addTypesFromDatatype( DatatypeType(childType.toType()) );
}
- DatatypeType dt = DatatypeType(childType.toType());
- if( dt.isParametric() ){
- Debug("typecheck-idt") << "typecheck parameterized ascription: " << n << std::endl;
- Matcher m( dt );
- if( !m.doMatching( childType, t ) ){
- throw TypeCheckingExceptionPrivate(n, "matching failed for type ascription argument of parameterized datatype");
- }
- }else{
- Debug("typecheck-idt") << "typecheck test: " << n << std::endl;
- if(t != childType) {
- throw TypeCheckingExceptionPrivate(n, "bad type for type ascription argument");
- }
+ if( !m.doMatching( childType, t ) ){
+ throw TypeCheckingExceptionPrivate(n, "matching failed for type ascription argument of parameterized datatype");
}
+
}
return t;
}
typedef expr::Attribute<expr::attr::DatatypeGroundTermTag, Node> DatatypeGroundTermAttr;
const Datatype& Datatype::datatypeOf(Expr item) {
+ ExprManagerScope ems(item);
TypeNode t = Node::fromExpr(item).getType();
switch(t.getKind()) {
case kind::CONSTRUCTOR_TYPE:
}
size_t Datatype::indexOf(Expr item) {
+ ExprManagerScope ems(item);
AssertArgument(item.getType().isConstructor() ||
item.getType().isTester() ||
item.getType().isSelector(),
item,
"arg must be a datatype constructor, selector, or tester");
TNode n = Node::fromExpr(item);
- Assert(n.hasAttribute(DatatypeIndexAttr()));
- return n.getAttribute(DatatypeIndexAttr());
+ if( item.getKind()==kind::APPLY_TYPE_ASCRIPTION ){
+ return indexOf( item[0] );
+ }else{
+ Assert(n.hasAttribute(DatatypeIndexAttr()));
+ return n.getAttribute(DatatypeIndexAttr());
+ }
}
void Datatype::resolve(ExprManager* em,
for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
// prefer the nullary constructor
if( groundTerm.isNull() && (*i).getNumArgs() == 0) {
- groundTerm = (*i).getConstructor().getExprManager()->mkExpr(kind::APPLY_CONSTRUCTOR, (*i).getConstructor());
+ groundTerm = d_constructors[indexOf((*i).getConstructor())].mkGroundTerm( t );
+ //groundTerm = (*i).getConstructor().getExprManager()->mkExpr(kind::APPLY_CONSTRUCTOR, (*i).getConstructor());
self.setAttribute(DatatypeGroundTermAttr(), groundTerm);
Debug("datatypes-gt") << "constructed nullary: " << getName() << " => " << groundTerm << std::endl;
}
// if we get all the way here, we aren't well-founded
CheckArgument(false, *this, "this datatype is not well-founded, cannot construct a ground term!");
}else{
- if( t!=groundTerm.getType() ){
- groundTerm = NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION,
- NodeManager::currentNM()->mkConst(AscriptionType(t)), groundTerm).toExpr();
- }
return groundTerm;
}
}
vector<Type> subst;
m.getMatches(subst);
vector<Type> params = dt.getParameters();
- return d_constructor.getType().substitute(subst, params);
+ return d_constructor.getType().substitute(params, subst);
}
Expr Datatype::Constructor::getTester() const {
Expr Datatype::Constructor::mkGroundTerm( Type t ) const throw(AssertionException) {
CheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
- Debug("datatypes-gt") << "mkGroundTerm " << t << std::endl;
// we're using some internals, so we have to set up this library context
ExprManagerScope ems(d_constructor);
}
groundTerms.push_back(selType.mkGroundTerm());
}
-
+
groundTerm = getConstructor().getExprManager()->mkExpr(kind::APPLY_CONSTRUCTOR, groundTerms);
+ if( groundTerm.getType()!=t ){
+ Assert( Datatype::datatypeOf( d_constructor ).isParametric() );
+ //type is ambiguous, must apply type ascription
+ Debug("datatypes-gt") << "ambiguous type for " << groundTerm << ", ascribe to " << t << std::endl;
+ groundTerms[0] = getConstructor().getExprManager()->mkExpr(kind::APPLY_TYPE_ASCRIPTION,
+ getConstructor().getExprManager()->mkConst(AscriptionType(getSpecializedConstructorType(t))),
+ groundTerms[0]);
+ groundTerm = getConstructor().getExprManager()->mkExpr(kind::APPLY_CONSTRUCTOR, groundTerms);
+ }
self.setAttribute(DatatypeGroundTermAttr(), groundTerm);
return groundTerm;
}
public:
Matcher(){}
Matcher( DatatypeType dt ){
+ addTypesFromDatatype( dt );
+ }
+ ~Matcher(){}
+
+ void addTypesFromDatatype( DatatypeType dt ){
std::vector< Type > argTypes = dt.getParamTypes();
addTypes( argTypes );
Debug("typecheck-idt") << "instantiating matcher for " << dt << std::endl;
}
}
}
- ~Matcher(){}
-
void addType( Type t ){
d_types.push_back( TypeNode::fromType( t ) );
d_match.push_back( TypeNode::null() );
}
}
- bool doMatching( TypeNode base, TypeNode match ){
- Debug("typecheck-idt") << "doMatching() : " << base << " : " << match << std::endl;
- std::vector< TypeNode >::iterator i = std::find( d_types.begin(), d_types.end(), base );
+ bool doMatching( TypeNode pattern, TypeNode tn ){
+ Debug("typecheck-idt") << "doMatching() : " << pattern << " : " << tn << std::endl;
+ std::vector< TypeNode >::iterator i = std::find( d_types.begin(), d_types.end(), pattern );
if( i!=d_types.end() ){
int index = i - d_types.begin();
- Debug("typecheck-idt") << "++ match on " << index << " : " << d_match[index] << std::endl;
- if( !d_match[index].isNull() && d_match[index]!=match ){
+ if( !d_match[index].isNull() && d_match[index]!=tn ){
return false;
}else{
- d_match[ i - d_types.begin() ] = match;
+ d_match[ i - d_types.begin() ] = tn;
return true;
}
- }else if( base==match ){
+ }else if( pattern==tn ){
return true;
- }else if( base.getKind()!=match.getKind() || base.getNumChildren()!=match.getNumChildren() ){
+ }else if( pattern.getKind()!=tn.getKind() || pattern.getNumChildren()!=tn.getNumChildren() ){
return false;
}else{
- for( int i=0; i<(int)base.getNumChildren(); i++ ){
- if( !doMatching( base[i], match[i] ) ){
+ for( int i=0; i<(int)pattern.getNumChildren(); i++ ){
+ if( !doMatching( pattern[i], tn[i] ) ){
return false;
}
}