Parser::addOperator(kind::APPLY_CONSTRUCTOR);
Parser::addOperator(kind::APPLY_TESTER);
Parser::addOperator(kind::APPLY_SELECTOR);
+ Parser::addOperator(kind::APPLY_SELECTOR_TOTAL);
break;
case THEORY_STRINGS:
break;
case kind::APPLY_CONSTRUCTOR:
case kind::APPLY_SELECTOR:
+ case kind::APPLY_SELECTOR_TOTAL:
case kind::APPLY_TESTER:
toStream(op, n.getOperator(), depth, types, false);
break;
case kind::APPLY_TESTER:
case kind::APPLY_CONSTRUCTOR:
case kind::APPLY_SELECTOR:
+ case kind::APPLY_SELECTOR_TOTAL:
case kind::PARAMETRIC_DATATYPE:
break;
NodeBuilder<> appctorb(kind::APPLY_CONSTRUCTOR);
appctorb << (*dt2)[i].getConstructor();
for(size_t j = 0; j < ctor.getNumArgs(); ++j) {
- appctorb << rewriteAs(NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR, ctor[j].getSelector(), in), TypeNode::fromType(SelectorType((*dt2)[i][j].getSelector().getType()).getRangeType()));
+ appctorb << rewriteAs(NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR_TOTAL, ctor[j].getSelector(), in), TypeNode::fromType(SelectorType((*dt2)[i][j].getSelector().getType()).getRangeType()));
}
Node appctor = appctorb;
if(i == 0) {
for(size_t j = 0; j < ctor.getNumArgs(); ++j) {
TypeNode asType = TypeNode::fromType(SelectorType((*dt2)[i][j].getSelector().getType()).getRangeType());
asType = asType.substitute(fromParams.begin(), fromParams.end(), toParams.begin(), toParams.end());
- appctorb << rewriteAs(NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR, ctor[j].getSelector(), in), asType);
+ appctorb << rewriteAs(NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR_TOTAL, ctor[j].getSelector(), in), asType);
}
Node appctor = appctorb;
if(i == 0) {
const Record& rec = in[0].getType().getAttribute(expr::DatatypeRecordAttr()).getConst<Record>();
return RewriteResponse(REWRITE_DONE, in[0][rec.getIndex(in.getOperator().getConst<RecordSelect>().getField())]);
}
- if(in.getKind() == kind::APPLY_SELECTOR &&
+ if(in.getKind() == kind::APPLY_SELECTOR_TOTAL &&
(in[0].getKind() == kind::TUPLE || in[0].getKind() == kind::RECORD)) {
// These strange (half-tuple-converted) terms can be created by
// the system if you have something like "foo.1" for a tuple
Debug("tuprec") << "==> returning " << in[0][selectorIndex] << std::endl;
return RewriteResponse(REWRITE_DONE, in[0][selectorIndex]);
}
- if(in.getKind() == kind::APPLY_SELECTOR &&
+ if(in.getKind() == kind::APPLY_SELECTOR_TOTAL &&
in[0].getKind() == kind::APPLY_CONSTRUCTOR) {
// Have to be careful not to rewrite well-typed expressions
// where the selector doesn't match the constructor,
parameterized APPLY_CONSTRUCTOR APPLY_TYPE_ASCRIPTION 0: "constructor application"
parameterized APPLY_SELECTOR SELECTOR_TYPE 1: "selector application"
+parameterized APPLY_SELECTOR_TOTAL [SELECTOR_TYPE] 1: "selector application (total)"
parameterized APPLY_TESTER TESTER_TYPE 1: "tester application"
typerule APPLY_CONSTRUCTOR ::CVC4::theory::datatypes::DatatypeConstructorTypeRule
typerule APPLY_SELECTOR ::CVC4::theory::datatypes::DatatypeSelectorTypeRule
+typerule APPLY_SELECTOR_TOTAL ::CVC4::theory::datatypes::DatatypeSelectorTypeRule
typerule APPLY_TESTER ::CVC4::theory::datatypes::DatatypeTesterTypeRule
typerule APPLY_TYPE_ASCRIPTION ::CVC4::theory::datatypes::DatatypeAscriptionTypeRule
// The kinds we are treating as function application in congruence
d_equalityEngine.addFunctionKind(kind::APPLY_CONSTRUCTOR);
- d_equalityEngine.addFunctionKind(kind::APPLY_SELECTOR);
+ d_equalityEngine.addFunctionKind(kind::APPLY_SELECTOR_TOTAL);
d_equalityEngine.addFunctionKind(kind::APPLY_TESTER);
}
flushPendingFacts();
}
+Node TheoryDatatypes::expandDefinition(LogicRequest &logicRequest, Node n) {
+ switch( n.getKind() ){
+ case kind::APPLY_SELECTOR: {
+ Node selector = n.getOperator();
+ Expr selectorExpr = selector.toExpr();
+ size_t selectorIndex = Datatype::cindexOf(selectorExpr);
+ const Datatype& dt = Datatype::datatypeOf(selectorExpr);
+ const DatatypeConstructor& c = dt[selectorIndex];
+ Expr tester = c.getTester();
+ Node tst = NodeManager::currentNM()->mkNode( kind::APPLY_TESTER, Node::fromExpr( tester ), n[0] );
+ tst = Rewriter::rewrite( tst );
+ Node sel = NodeManager::currentNM()->mkNode( kind::APPLY_SELECTOR_TOTAL, Node::fromExpr( selectorExpr ), n[0] );
+ Node n_ret;
+ if( tst==NodeManager::currentNM()->mkConst( true ) ){
+ n_ret = sel;
+ }else{
+ if( d_exp_def_skolem.find( selector )==d_exp_def_skolem.end() ){
+ std::stringstream ss;
+ ss << selector << "_uf";
+ d_exp_def_skolem[ selector ] = NodeManager::currentNM()->mkSkolem( ss.str().c_str(),
+ NodeManager::currentNM()->mkFunctionType( n[0].getType(), n.getType() ) );
+ }
+ Node sk = NodeManager::currentNM()->mkNode( kind::APPLY_UF, d_exp_def_skolem[ selector ], n[0] );
+ if( tst==NodeManager::currentNM()->mkConst( false ) ){
+ n_ret = sk;
+ }else{
+ n_ret = NodeManager::currentNM()->mkNode( kind::ITE, tst, sel, sk );
+ }
+ }
+ //n_ret = Rewriter::rewrite( n_ret );
+ Trace("dt-expand") << "Expand def : " << n << " to " << n_ret << std::endl;
+ return n_ret;
+ }
+ break;
+ default:
+ return n;
+ break;
+ }
+ Unreachable();
+}
+
void TheoryDatatypes::presolve() {
Debug("datatypes") << "TheoryDatatypes::presolve()" << endl;
}
}
TypeNode dtt = NodeManager::currentNM()->getDatatypeForTupleRecord(t);
const Datatype& dt = DatatypeType(dtt.toType()).getDatatype();
- return NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR, Node::fromExpr(dt[0][in.getOperator().getConst<TupleSelect>().getIndex()].getSelector()), in[0]);
+ return NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR_TOTAL, Node::fromExpr(dt[0][in.getOperator().getConst<TupleSelect>().getIndex()].getSelector()), in[0]);
} else if(in.getKind() == kind::RECORD_SELECT) {
TypeNode t = in[0].getType();
if(t.hasAttribute(expr::DatatypeRecordAttr())) {
}
TypeNode dtt = NodeManager::currentNM()->getDatatypeForTupleRecord(t);
const Datatype& dt = DatatypeType(dtt.toType()).getDatatype();
- return NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR, Node::fromExpr(dt[0][in.getOperator().getConst<RecordSelect>().getField()].getSelector()), in[0]);
+ return NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR_TOTAL, Node::fromExpr(dt[0][in.getOperator().getConst<RecordSelect>().getField()].getSelector()), in[0]);
}
TypeNode t = in.getType();
b << in[1];
Debug("tuprec") << "arg " << i << " gets updated to " << in[1] << std::endl;
} else {
- b << NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR, Node::fromExpr(dt[0][i].getSelector()), in[0]);
+ b << NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR_TOTAL, Node::fromExpr(dt[0][i].getSelector()), in[0]);
Debug("tuprec") << "arg " << i << " copies " << b[b.getNumChildren() - 1] << std::endl;
}
}
}
void TheoryDatatypes::collapseSelector( Node s, Node c ) {
- Node r = NodeManager::currentNM()->mkNode( kind::APPLY_SELECTOR, s.getOperator(), c );
+ Node r = NodeManager::currentNM()->mkNode( kind::APPLY_SELECTOR_TOTAL, s.getOperator(), c );
Node rr = Rewriter::rewrite( r );
//if( r!=rr ){
//Node eq_exp = NodeManager::currentNM()->mkConst(true);
//eqc->d_selectors = true;
}
*/
- }else if( n.getKind() == APPLY_SELECTOR ){
+ }else if( n.getKind() == APPLY_SELECTOR_TOTAL ){
//we must also record which selectors exist
Debug("datatypes") << " Found selector " << n << endl;
if (n.getType().isBoolean()) {
std::vector< Node > children;
children.push_back( Node::fromExpr( dt[index].getConstructor() ) );
for( int i=0; i<(int)dt[index].getNumArgs(); i++ ){
- Node nc = NodeManager::currentNM()->mkNode( APPLY_SELECTOR, Node::fromExpr( dt[index][i].getSelector() ), n );
+ Node nc = NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[index][i].getSelector() ), n );
if( mkVar ){
TypeNode tn = nc.getType();
if( dt.isParametric() ){
std::vector< Node > d_pending;
std::map< Node, Node > d_pending_exp;
std::vector< Node > d_pending_merge;
+ /** expand definition skolem functions */
+ std::map< Node, Node > d_exp_def_skolem;
private:
/** assert fact */
void assertFact( Node fact, Node exp );
void check(Effort e);
void preRegisterTerm(TNode n);
+ Node expandDefinition(LogicRequest &logicRequest, Node n);
Node ppRewrite(TNode n);
void presolve();
void addSharedTerm(TNode t);
struct DatatypeSelectorTypeRule {
inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
throw(TypeCheckingExceptionPrivate) {
- Assert(n.getKind() == kind::APPLY_SELECTOR);
+ Assert(n.getKind() == kind::APPLY_SELECTOR || n.getKind() == kind::APPLY_SELECTOR_TOTAL );
TypeNode selType = n.getOperator().getType(check);
Type t = selType[0].toType();
Assert( t.isDatatype() );
+ Use instantiation algorithm that mimics Inst-Gen calculus. \n\
\n\
gen-ev \n\
-+ Default, use model-based quantifier instantiation algorithm from CADE 24 finite\n\
- model finding paper.\n\
++ Use model-based quantifier instantiation algorithm from CADE 24 finite\n\
+ model finding paper based on generalizing evaluations.\n\
\n\
fmc-interval \n\
+ Same as default, but with intervals for models of integer functions.\n\
partial \n\
+ Apply QCF algorithm to instantiate heuristically as well. \n\
\n\
-partial \n\
-+ Apply QCF to instantiate heuristically as well. \n\
-\n\
mc \n\
+ Apply QCF algorithm in a complete way, so that a model is ensured when it fails. \n\
\n\
}
inline MbqiMode stringToMbqiMode(std::string option, std::string optarg, SmtEngine* smt) throw(OptionException) {
- if(optarg == "gen-ev") {
+ if(optarg == "gen-ev") {
return MBQI_GEN_EVAL;
- } else if(optarg == "none") {
+ } else if(optarg == "none") {
return MBQI_NONE;
- } else if(optarg == "instgen") {
+ } else if(optarg == "instgen") {
return MBQI_INST_GEN;
- } else if(optarg == "default" || optarg == "fmc") {
+ } else if(optarg == "default" || optarg == "fmc") {
return MBQI_FMC;
- } else if(optarg == "fmc-interval") {
+ } else if(optarg == "fmc-interval") {
return MBQI_FMC_INTERVAL;
- } else if(optarg == "interval") {
+ } else if(optarg == "interval") {
return MBQI_INTERVAL;
- } else if(optarg == "trust") {
+ } else if(optarg == "trust") {
return MBQI_TRUST;
- } else if(optarg == "help") {
+ } else if(optarg == "help") {
puts(mbqiModeHelp.c_str());
exit(1);
} else {
\r
bool MatchGen::isHandledUfTerm( TNode n ) {\r
return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||\r
- n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR || n.getKind()==APPLY_TESTER;// || n.getKind()==GEQ;\r
+ n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;\r
}\r
\r
Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {\r
bool Trigger::isAtomicTrigger( Node n ){
return ( n.getKind()==APPLY_UF && !n.getOperator().getAttribute(NoMatchAttribute()) ) || n.getKind()==SELECT || n.getKind()==STORE ||
- n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR || n.getKind()==APPLY_TESTER;
+ n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
}
bool Trigger::isSimpleTrigger( Node n ){
if( isAtomicTrigger( n ) ){
d_equalityEngine->addFunctionKind(kind::SELECT);
// d_equalityEngine->addFunctionKind(kind::STORE);
d_equalityEngine->addFunctionKind(kind::APPLY_CONSTRUCTOR);
- d_equalityEngine->addFunctionKind(kind::APPLY_SELECTOR);
+ d_equalityEngine->addFunctionKind(kind::APPLY_SELECTOR_TOTAL);
d_equalityEngine->addFunctionKind(kind::APPLY_TESTER);
d_eeContext->push();
}
bool TheoryEngineModelBuilder::isAssignable(TNode n)
{
- return (n.isVar() || n.getKind() == kind::APPLY_UF || n.getKind() == kind::SELECT || n.getKind() == kind::APPLY_SELECTOR);
+ return (n.isVar() || n.getKind() == kind::APPLY_UF || n.getKind() == kind::SELECT || n.getKind() == kind::APPLY_SELECTOR_TOTAL);
}
datatype0.cvc \
datatype1.cvc \
datatype2.cvc \
- datatype3.cvc \
datatype4.cvc \
datatype13.cvc \
empty_tuprec.cvc \
FAILING_TESTS = \
datatype-dump.cvc
+# takes a long time to build model on debug : datatype3.cvc
+
EXTRA_DIST = $(TESTS)
if CVC4_BUILD_PROFILE_COMPETITION
-% EXPECT: valid
+% EXPECT: invalid
DATATYPE
tree = node(left : tree, right : tree) | leaf
-% EXPECT: valid
+% EXPECT: invalid
DATATYPE
tree = node(left : tree, right : tree) | leaf
-% EXPECT: valid
+% EXPECT: invalid
DATATYPE
nat = succ(pred : nat) | zero
END;