d_registered_terms_cache(u),
d_preproc_cache(u),
d_proxy_var(u),
+ d_proxy_var_to_length(u),
d_neg_ctn_eqlen(u),
d_neg_ctn_ulen(u),
d_pos_ctn_cached(u),
++(d_statistics.d_splits);
}
} else {
- if( n.getKind()==kind::STRING_CONCAT ){
- //normalize wrt proxy variables
-
- }
-
-
Node sk = mkSkolemS("lsym", 2);
StringsProxyVarAttribute spva;
sk.setAttribute(spva,true);
if( n.getKind() == kind::STRING_CONCAT ) {
std::vector<Node> node_vec;
for( unsigned i=0; i<n.getNumChildren(); i++ ) {
- Node lni = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n[i] );
- node_vec.push_back(lni);
+ if( n[i].getAttribute(StringsProxyVarAttribute()) ){
+ Assert( d_proxy_var_to_length.find( n[i] )!=d_proxy_var_to_length.end() );
+ node_vec.push_back( d_proxy_var_to_length[n[i]] );
+ }else{
+ Node lni = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, n[i] );
+ node_vec.push_back(lni);
+ }
}
lsum = NodeManager::currentNM()->mkNode( kind::PLUS, node_vec );
} else if( n.getKind() == kind::CONST_STRING ) {
lsum = NodeManager::currentNM()->mkConst( ::CVC4::Rational( n.getConst<String>().size() ) );
}
+ lsum = Rewriter::rewrite( lsum );
+ d_proxy_var_to_length[sk] = lsum;
Node ceq = Rewriter::rewrite( skl.eqNode( lsum ) );
Trace("strings-lemma") << "Strings::Lemma LENGTH : " << ceq << std::endl;
Trace("strings-lemma-debug") << " prerewrite : " << skl.eqNode( lsum ) << std::endl;
}
void TheoryStrings::sendInfer( Node eq_exp, Node eq, const char * c ) {
+ Trace("strings-infer-debug") << "infer : " << eq << " from " << eq_exp << std::endl;
eq = Rewriter::rewrite( eq );
if( eq==d_false || eq.getKind()==kind::OR ) {
sendLemma( eq_exp, eq, c );
Node ss;
if( ns[i].getAttribute(StringsProxyVarAttribute()) ){
ss = ns[i];
- }else{
+ }else if( ns[i].isConst() ){
NodeNodeMap::const_iterator it = d_proxy_var.find( ns[i] );
if( it!=d_proxy_var.end() ){
ss = (*it).second;
while( !eqc_i.isFinished() ) {
Node n = (*eqc_i);
if( std::find( d_congruent.begin(), d_congruent.end(), n )==d_congruent.end() ){
- Trace("strings-cycle") << "Check term : " << n << std::endl;
+ Trace("strings-cycle") << eqc << " check term : " << n << " in " << eqc << std::endl;
if( n.getKind() == kind::STRING_CONCAT ) {
if( eqc!=d_emptyString_r ){
d_eqc[eqc].push_back( n );
//for non-empty eqc, recurse and see if we find a loop
Node ncy = checkCycles( nr, curr, exp );
if( !ncy.isNull() ){
+ Trace("strings-cycle") << eqc << " cycle: " << ncy << " at " << n << "[" << i << "] : " << n[i] << std::endl;
+ if( n!=eqc ){
+ exp.push_back( n.eqNode( eqc ) );
+ }
+ if( nr!=n[i] ){
+ exp.push_back( nr.eqNode( n[i] ) );
+ }
if( ncy==eqc ){
//can infer all other components must be empty
for( unsigned j=0; j<n.getNumChildren(); j++ ){
//should find a non-empty component, otherwise would have been singular congruent (I_Norm_S)
Assert( false );
}else{
- if( n!=eqc ){
- exp.push_back( n.eqNode( eqc ) );
- }
- if( nr!=n[i] ){
- exp.push_back( nr.eqNode( n[i] ) );
- }
return ncy;
}
}else{
lt = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, lt );
Node r = d_equalityEngine.getRepresentative( lt );
if( eqc_to_leqc.find( r )==eqc_to_leqc.end() ){
- eqc_to_leqc[r] = leqc_counter;
- leqc_to_eqc[leqc_counter] = r;
- leqc_counter++;
+ eqc_to_leqc[r] = leqc_counter;
+ leqc_to_eqc[leqc_counter] = r;
+ leqc_counter++;
}
eqc_to_strings[ eqc_to_leqc[r] ].push_back( eqc );
}else{
Node sk3 = NodeManager::currentNM()->mkSkolem( "io3", NodeManager::currentNM()->stringType(), "created for indexof" );
Node sk4 = NodeManager::currentNM()->mkSkolem( "io4", NodeManager::currentNM()->stringType(), "created for indexof" );
Node skk = NodeManager::currentNM()->mkSkolem( "iok", NodeManager::currentNM()->integerType(), "created for indexof" );
- Node st = NodeManager::currentNM()->mkNode( kind::STRING_SUBSTR_TOTAL, t[0], t[2], NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, t[0] ) );
+ Node st = NodeManager::currentNM()->mkNode( kind::STRING_SUBSTR_TOTAL, t[0], t[2], NodeManager::currentNM()->mkNode( kind::MINUS, NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, t[0] ), t[2] ) );
Node eq = st.eqNode( NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, sk2, sk3, sk4 ) );
new_nodes.push_back( eq );
Node negone = NodeManager::currentNM()->mkConst( ::CVC4::Rational(-1) );
return NodeManager::currentNM()->mkConst( false );
}
}else if( rc.getKind()==kind::REGEXP_INTER || rc.getKind()==kind::REGEXP_UNION ){
- //TODO
+ //TODO? note this is only propagation : cannot make choices
}else if( rc.getKind()==kind::REGEXP_STAR ){
//TODO
}
}else if(x != node[0] || r != node[1]) {
retNode = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, x, r );
}
-
+
//do simple consumes
if( retNode==node ){
if( r.getKind()==kind::REGEXP_STAR ){
retNode = NodeManager::currentNM()->mkNode(kind::PLUS, node_vec);
}
}
- } else if(node.getKind() == kind::STRING_SUBSTR_TOTAL) {
+ } else if( node.getKind() == kind::STRING_SUBSTR_TOTAL ){
Node zero = NodeManager::currentNM()->mkConst( ::CVC4::Rational(0) );
if(node[2] == zero) {
retNode = NodeManager::currentNM()->mkConst( ::CVC4::String("") );