void DatatypesEnumerator::init(){ //Assert(type.isDatatype()); Debug("dt-enum") << "datatype is datatype? " << d_type.isDatatype() << std::endl; Debug("dt-enum") << "datatype is kind " << d_type.getKind() << std::endl; Debug("dt-enum") << "datatype is " << d_type << std::endl; Debug("dt-enum") << "properties : " << d_datatype.isCodatatype() << " " << d_datatype.isRecursiveSingleton( d_type.toType() ); Debug("dt-enum") << " " << d_datatype.isInterpretedFinite( d_type.toType() ) << std::endl; if( d_datatype.isCodatatype() && hasCyclesDt( d_datatype ) ){ //start with uninterpreted constant d_zeroCtor = 0; d_has_debruijn = 1; d_sel_types.push_back( std::vector< TypeNode >() ); d_sel_index.push_back( std::vector< unsigned >() ); d_sel_sum.push_back( -1 ); }else{ // find the "zero" constructor via mkGroundTerm Debug("dt-enum-debug") << "make ground term..." << std::endl; Node t = d_type.mkGroundTerm(); Debug("dt-enum-debug") << "done : " << t << std::endl; Assert( t.getKind()==kind::APPLY_CONSTRUCTOR ); // start with the constructor for which a ground term is constructed d_zeroCtor = datatypes::DatatypesRewriter::indexOf(t.getOperator()); d_has_debruijn = 0; } Debug("dt-enum") << "zero ctor : " << d_zeroCtor << std::endl; d_ctor = d_zeroCtor; for( unsigned i=0; i<d_datatype.getNumConstructors(); ++i ){ d_sel_types.push_back( std::vector< TypeNode >() ); d_sel_index.push_back( std::vector< unsigned >() ); d_sel_sum.push_back( -1 ); DatatypeConstructor ctor = d_datatype[i]; Type typ; if( d_datatype.isParametric() ){ typ = ctor.getSpecializedConstructorType(d_type.toType()); } for( unsigned a = 0; a < ctor.getNumArgs(); ++a ){ TypeNode tn; if( d_datatype.isParametric() ){ tn = TypeNode::fromType( typ )[a]; }else{ tn = Node::fromExpr(ctor[a].getSelector()).getType()[1]; } d_sel_types.back().push_back( tn ); d_sel_index.back().push_back( 0 ); } if( !d_sel_index.back().empty() ){ d_sel_index.back().pop_back(); } } d_size_limit = 0; //set up initial conditions (should always succeed) ++*this; //increment( d_ctor ); AlwaysAssert( !isFinished() ); }
Node DatatypesEnumerator::getCurrentTerm( unsigned index ){ Debug("dt-enum-debug") << "Get current term at " << index << " " << d_type << std::endl; Node ret; if( index<d_has_debruijn ){ if( d_child_enum ){ ret = NodeManager::currentNM()->mkConst(UninterpretedConstant(d_type.toType(), d_size_limit)); }else{ //no top-level variables return Node::null(); } }else{ Debug("dt-enum-debug") << "Look at constructor " << (index - d_has_debruijn) << std::endl; DatatypeConstructor ctor = d_datatype[index - d_has_debruijn]; Debug("dt-enum-debug") << "Check last term..." << std::endl; //we first check if the last argument (which is forced to make sum of iterated arguments equal to d_size_limit) is defined Node lc; if( ctor.getNumArgs()>0 ){ Assert( index<d_sel_types.size() ); Assert( ctor.getNumArgs()-1<d_sel_types[index].size() ); lc = getTermEnum( d_sel_types[index][ctor.getNumArgs()-1], d_size_limit - d_sel_sum[index] ); if( lc.isNull() ){ Debug("dt-enum-debug") << "Current infeasible." << std::endl; return Node::null(); } } Debug("dt-enum-debug") << "Get constructor..." << std::endl; NodeBuilder<> b(kind::APPLY_CONSTRUCTOR); Type typ; if( d_datatype.isParametric() ){ typ = ctor.getSpecializedConstructorType(d_type.toType()); b << NodeManager::currentNM()->mkNode(kind::APPLY_TYPE_ASCRIPTION, NodeManager::currentNM()->mkConst(AscriptionType(typ)), Node::fromExpr( ctor.getConstructor() ) ); }else{ b << ctor.getConstructor(); } Debug("dt-enum-debug") << "Get arguments..." << std::endl; if( ctor.getNumArgs()>0 ){ Assert( index<d_sel_types.size() ); Assert( index<d_sel_index.size() ); Assert( d_sel_types[index].size()==ctor.getNumArgs() ); Assert( d_sel_index[index].size()==ctor.getNumArgs()-1 ); for( int i=0; i<(int)(ctor.getNumArgs()-1); i++ ){ Node c = getTermEnum( d_sel_types[index][i], d_sel_index[index][i] ); Assert( !c.isNull() ); b << c; } b << lc; } Node nnn = Node(b); Debug("dt-enum-debug") << "Return... " << nnn << std::endl; ret = nnn; } if( !d_child_enum && d_has_debruijn ){ Node nret = DatatypesRewriter::normalizeCodatatypeConstant( ret ); if( nret!=ret ){ if( nret.isNull() ){ Trace("dt-enum-nn") << "Invalid constant : " << ret << std::endl; }else{ Trace("dt-enum-nn") << "Non-normal constant : " << ret << std::endl; Trace("dt-enum-nn") << " ...normal form is : " << nret << std::endl; } return Node::null(); } } return ret; }