void equality_domaint::project_on_vars( valuet &value, const var_sett &vars, exprt &result) { #if 0 if(templ.size()==0) return domaint::project_on_vars(value, vars, result); #endif equ_valuet &v=static_cast<equ_valuet &>(value); exprt::operandst c; for(unsigned index=0; index<templ.size(); index++) { const var_pairt &vv=templ[index].var_pair; #if 0 std::cout << vv.second << std::endl; #endif if(vars.find(vv.first)==vars.end() || (vars.find(vv.second)==vars.end() && !(vv.second.id()==ID_constant && to_constant_expr(vv.second).get_value()=="NULL"))) continue; if(v.equs.same_set(vv.first, vv.second)) { if(templ[index].kind==LOOP) c.push_back( implies_exprt( templ[index].pre_guard, equal_exprt(vv.first, vv.second))); else c.push_back(equal_exprt(vv.first, vv.second)); } } for(index_sett::const_iterator it=v.disequs.begin(); it!=v.disequs.end(); it++) { const var_pairt &vv=templ[*it].var_pair; if(vars.find(vv.first)==vars.end() || (vars.find(vv.second)==vars.end() && !(vv.second.id()==ID_constant && to_constant_expr(vv.second).get_value()=="NULL"))) continue; if(templ[*it].kind==LOOP) c.push_back( implies_exprt( templ[*it].pre_guard, notequal_exprt(vv.first, vv.second))); else c.push_back(notequal_exprt(vv.first, vv.second)); } result=conjunction(c); }
exprt equality_domaint::get_pre_disequ_constraint(unsigned index) { assert(index<templ.size()); const template_rowt &templ_row=templ[index]; if(templ_row.kind==OUT || templ_row.kind==OUTL) return true_exprt(); const var_pairt &vv=templ_row.var_pair; return implies_exprt(templ_row.pre_guard, notequal_exprt(vv.first, vv.second)); }
/// add axioms stating that the result is true exactly when the strings /// represented by the arguments are equal /// \par parameters: function application with two string arguments /// \return a expression of Boolean type exprt string_constraint_generatort::add_axioms_for_equals( const function_application_exprt &f) { assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); symbol_exprt eq=fresh_boolean("equal"); typecast_exprt tc_eq(eq, f.type()); string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); typet index_type=s1.length().type(); // We want to write: // eq <=> (s1.length=s2.length &&forall i<s1.length. s1[i]=s2[i]) // We add axioms: // a1 : eq => s1.length=s2.length // a2 : forall i<s1.length. eq => s1[i]=s2[i] // a3 : !eq => s1.length!=s2.length // || (witness<s1.length &&s1[witness]!=s2[witness]) implies_exprt a1(eq, s1.axiom_for_has_same_length_as(s2)); axioms.push_back(a1); symbol_exprt qvar=fresh_univ_index("QA_equal", index_type); string_constraintt a2(qvar, s1.length(), eq, equal_exprt(s1[qvar], s2[qvar])); axioms.push_back(a2); symbol_exprt witness=fresh_exist_index("witness_unequal", index_type); exprt zero=from_integer(0, index_type); and_exprt bound_witness( binary_relation_exprt(witness, ID_lt, s1.length()), binary_relation_exprt(witness, ID_ge, zero)); and_exprt witnessing(bound_witness, notequal_exprt(s1[witness], s2[witness])); implies_exprt a3( not_exprt(eq), or_exprt(notequal_exprt(s1.length(), s2.length()), witnessing)); axioms.push_back(a3); return tc_eq; }
/// add axioms corresponding to the String.equalsIgnoreCase java function /// \par parameters: function application with two string arguments /// \return a Boolean expression exprt string_constraint_generatort::add_axioms_for_equals_ignore_case( const function_application_exprt &f) { assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); symbol_exprt eq=fresh_boolean("equal_ignore_case"); typecast_exprt tc_eq(eq, f.type()); string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); typet char_type=to_refined_string_type(s1.type()).get_char_type(); exprt char_a=constant_char('a', char_type); exprt char_A=constant_char('A', char_type); exprt char_Z=constant_char('Z', char_type); typet index_type=s1.length().type(); // We add axioms: // a1 : eq => |s1|=|s2| // a2 : forall qvar, 0<=qvar<|s1|, // eq => char_equal_ignore_case(s1[qvar],s2[qvar]); // a3 : !eq => |s1|!=s2 || (0 <=witness<|s1| &&!char_equal_ignore_case) implies_exprt a1(eq, s1.axiom_for_has_same_length_as(s2)); axioms.push_back(a1); symbol_exprt qvar=fresh_univ_index("QA_equal_ignore_case", index_type); exprt constr2=character_equals_ignore_case( s1[qvar], s2[qvar], char_a, char_A, char_Z); string_constraintt a2(qvar, s1.length(), eq, constr2); axioms.push_back(a2); symbol_exprt witness=fresh_exist_index( "witness_unequal_ignore_case", index_type); exprt zero=from_integer(0, witness.type()); and_exprt bound_witness( binary_relation_exprt(witness, ID_lt, s1.length()), binary_relation_exprt(witness, ID_ge, zero)); exprt witness_eq=character_equals_ignore_case( s1[witness], s2[witness], char_a, char_A, char_Z); not_exprt witness_diff(witness_eq); implies_exprt a3( not_exprt(eq), or_exprt( notequal_exprt(s1.length(), s2.length()), and_exprt(bound_witness, witness_diff))); axioms.push_back(a3); return tc_eq; }
exprt equality_domaint::get_post_not_disequ_constraint(unsigned index) { assert(index<templ.size()); const template_rowt &templ_row=templ[index]; if(templ_row.kind==IN) return true_exprt(); const var_pairt &vv=templ_row.var_pair; exprt c= and_exprt( templ_row.aux_expr, not_exprt( implies_exprt( templ_row.post_guard, notequal_exprt(vv.first, vv.second)))); rename(c); return c; }