mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
theory_str cleanup
This commit is contained in:
parent
3670fa64e6
commit
e699f25889
1 changed files with 5 additions and 158 deletions
|
@ -273,68 +273,6 @@ bool theory_str::internalize_term(app * term) {
|
|||
TRACE("t_str_axiom_bug", tout << "add " << mk_pp(e->get_owner(), m) << " to m_basicstr_axiom_todo" << std::endl;);
|
||||
}
|
||||
return true;
|
||||
|
||||
/* // what I had before
|
||||
SASSERT(!ctx.e_internalized(term));
|
||||
|
||||
unsigned num_args = term->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++)
|
||||
ctx.internalize(term->get_arg(i), false);
|
||||
|
||||
enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) :
|
||||
ctx.mk_enode(term, false, false, true);
|
||||
|
||||
if (is_attached_to_var(e))
|
||||
return false;
|
||||
|
||||
attach_new_th_var(e);
|
||||
|
||||
//if (is_concat(term)) {
|
||||
// instantiate_concat_axiom(e);
|
||||
//}
|
||||
*/
|
||||
|
||||
// TODO do we still need to do instantiate_concat_axiom()?
|
||||
|
||||
// partially from theory_seq::internalize_term()
|
||||
/*
|
||||
if (ctx.e_internalized(term)) {
|
||||
enode* e = ctx.get_enode(term);
|
||||
mk_var(e);
|
||||
return true;
|
||||
}
|
||||
TRACE("t_str_detail", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << std::endl;);
|
||||
unsigned num_args = term->get_num_args();
|
||||
expr* arg;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
arg = term->get_arg(i);
|
||||
mk_var(ensure_enode(arg));
|
||||
}
|
||||
if (m.is_bool(term)) {
|
||||
bool_var bv = ctx.mk_bool_var(term);
|
||||
ctx.set_var_theory(bv, get_id());
|
||||
ctx.mark_as_relevant(bv);
|
||||
}
|
||||
|
||||
enode* e = 0;
|
||||
if (ctx.e_internalized(term)) {
|
||||
e = ctx.get_enode(term);
|
||||
}
|
||||
else {
|
||||
e = ctx.mk_enode(term, false, m.is_bool(term), true);
|
||||
}
|
||||
|
||||
if (opt_EagerStringConstantLengthAssertions && m_strutil.is_string(term)) {
|
||||
TRACE("t_str", tout << "eagerly asserting length of string term " << mk_pp(term, m) << std::endl;);
|
||||
m_basicstr_axiom_todo.insert(e);
|
||||
TRACE("t_str_axiom_bug", tout << "add " << mk_pp(e->get_owner(), m) << " to m_basicstr_axiom_todo" << std::endl;);
|
||||
}
|
||||
|
||||
theory_var v = mk_var(e);
|
||||
TRACE("t_str_detail", tout << "term " << mk_ismt2_pp(term, get_manager()) << " = v#" << v << std::endl;);
|
||||
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
enode* theory_str::ensure_enode(expr* e) {
|
||||
|
@ -351,18 +289,11 @@ void theory_str::refresh_theory_var(expr * e) {
|
|||
enode * en = ensure_enode(e);
|
||||
theory_var v = mk_var(en);
|
||||
TRACE("t_str_detail", tout << "refresh " << mk_pp(e, get_manager()) << ": v#" << v << std::endl;);
|
||||
// TODO this is probably sub-optimal
|
||||
m_basicstr_axiom_todo.push_back(en);
|
||||
}
|
||||
|
||||
theory_var theory_str::mk_var(enode* n) {
|
||||
TRACE("t_str_detail", tout << "mk_var for " << mk_pp(n->get_owner(), get_manager()) << std::endl;);
|
||||
/*
|
||||
if (!m_strutil.is_string(n->get_owner())) {
|
||||
return null_theory_var;
|
||||
}
|
||||
*/
|
||||
// TODO this may require an overhaul of m_strutil.is_string() if things suddenly start working after the following change:
|
||||
ast_manager & m = get_manager();
|
||||
if (!(is_sort_of(m.get_sort(n->get_owner()), m_strutil.get_fid(), STRING_SORT))) {
|
||||
return null_theory_var;
|
||||
|
@ -503,9 +434,6 @@ app * theory_str::mk_int(rational & q) {
|
|||
return m_autil.mk_numeral(q, true);
|
||||
}
|
||||
|
||||
|
||||
// TODO refactor all of these so that they don't use variable counters, but use ast_manager::mk_fresh_const instead
|
||||
|
||||
expr * theory_str::mk_internal_lenTest_var(expr * node, int lTries) {
|
||||
ast_manager & m = get_manager();
|
||||
|
||||
|
@ -539,23 +467,6 @@ void theory_str::track_variable_scope(expr * var) {
|
|||
}
|
||||
|
||||
app * theory_str::mk_internal_xor_var() {
|
||||
/*
|
||||
ast_manager & m = get_manager();
|
||||
std::stringstream ss;
|
||||
ss << tmpXorVarCount;
|
||||
tmpXorVarCount++;
|
||||
std::string name = "$$_xor_" + ss.str();
|
||||
// Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), INT_SORT));
|
||||
sort * int_sort = m.mk_sort(m_autil.get_family_id(), INT_SORT);
|
||||
|
||||
char * new_buffer = alloc_svect(char, name.length() + 1);
|
||||
strcpy(new_buffer, name.c_str());
|
||||
symbol sym(new_buffer);
|
||||
|
||||
app * a = m.mk_const(m.mk_const_decl(sym, int_sort));
|
||||
m_trail.push_back(a);
|
||||
return a;
|
||||
*/
|
||||
return mk_int_var("$$_xor");
|
||||
}
|
||||
|
||||
|
@ -1069,7 +980,6 @@ void theory_str::instantiate_concat_axiom(enode * cat) {
|
|||
|
||||
// build LHS
|
||||
expr_ref len_xy(m);
|
||||
// TODO should we use str_util for these and other expressions?
|
||||
len_xy = mk_strlen(a_cat);
|
||||
SASSERT(len_xy);
|
||||
|
||||
|
@ -1106,15 +1016,12 @@ void theory_str::instantiate_concat_axiom(enode * cat) {
|
|||
* Length(x) == strlen(x)
|
||||
*/
|
||||
void theory_str::instantiate_basic_string_axioms(enode * str) {
|
||||
// TODO keep track of which enodes we have added axioms for, so we don't add the same ones twice?
|
||||
|
||||
context & ctx = get_context();
|
||||
ast_manager & m = get_manager();
|
||||
|
||||
TRACE("t_str_axiom_bug", tout << "set up basic string axioms on " << mk_pp(str->get_owner(), m) << std::endl;);
|
||||
|
||||
// TESTING: attempt to avoid a crash here when a variable goes out of scope
|
||||
// TODO this seems to work so we probably need to do this for other propagate checks, etc.
|
||||
if (str->get_iscope_lvl() > ctx.get_scope_level()) {
|
||||
TRACE("t_str_detail", tout << "WARNING: skipping axiom setup on out-of-scope string term" << std::endl;);
|
||||
return;
|
||||
|
@ -2596,7 +2503,6 @@ void theory_str::generate_mutual_exclusion(expr_ref_vector & terms) {
|
|||
literal_vector ls;
|
||||
for (unsigned i = 0; i < terms.size(); ++i) {
|
||||
expr * e = terms.get(i);
|
||||
// TODO make sure the terms are internalized, etc.?
|
||||
literal l = ctx.get_literal(e);
|
||||
ls.push_back(l);
|
||||
}
|
||||
|
@ -2605,28 +2511,6 @@ void theory_str::generate_mutual_exclusion(expr_ref_vector & terms) {
|
|||
|
||||
void theory_str::print_cut_var(expr * node, std::ofstream & xout) {
|
||||
ast_manager & m = get_manager();
|
||||
/*
|
||||
#ifdef DEBUGLOG
|
||||
__debugPrint(logFile, "\n>> CUT info of [");
|
||||
printZ3Node(t, node);
|
||||
__debugPrint(logFile, "]\n");
|
||||
|
||||
if (cut_VARMap.find(node) != cut_VARMap.end()) {
|
||||
if (!cut_VARMap[node].empty()) {
|
||||
__debugPrint(logFile, "[%2d] {", cut_VARMap[node].top()->level);
|
||||
std::map<Z3_ast, int>::iterator itor = cut_VARMap[node].top()->vars.begin();
|
||||
for (; itor != cut_VARMap[node].top()->vars.end(); itor++) {
|
||||
printZ3Node(t, itor->first);
|
||||
__debugPrint(logFile, ", ");
|
||||
}
|
||||
__debugPrint(logFile, "}\n");
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
__debugPrint(logFile, "------------------------\n\n");
|
||||
#endif
|
||||
*/
|
||||
xout << "Cut info of " << mk_pp(node, m) << std::endl;
|
||||
if (cut_var_map.contains(node)) {
|
||||
if (!cut_var_map[node].empty()) {
|
||||
|
@ -2924,8 +2808,6 @@ bool theory_str::will_result_in_overlap(expr * lhs, expr * rhs) {
|
|||
expr * m = to_app(new_nn2)->get_arg(0);
|
||||
expr * n = to_app(new_nn2)->get_arg(1);
|
||||
|
||||
// TODO is it too slow to perform length checks here to avoid false positives?
|
||||
|
||||
if (has_self_cut(m, y)) {
|
||||
TRACE("t_str_detail", tout << "Possible overlap found" << std::endl; print_cut_var(m, tout); print_cut_var(y, tout););
|
||||
return true;
|
||||
|
@ -3193,7 +3075,6 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
|||
t2 = varForBreakConcat[key2][1];
|
||||
xorFlag = varForBreakConcat[key2][2];
|
||||
}
|
||||
// TODO do I need to refresh the xorFlag, which is an integer var, and if so, how?
|
||||
refresh_theory_var(t1);
|
||||
add_nonempty_constraint(t1);
|
||||
refresh_theory_var(t2);
|
||||
|
@ -3252,7 +3133,7 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
|||
add_theory_aware_branching_info(tester, m_params.m_OverlapTheoryAwarePriority, l_true);
|
||||
} else {
|
||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||
// TODO printCutVar(m, y);
|
||||
TRACE("t_str_detail", {print_cut_var(m, tout); print_cut_var(y, tout);});
|
||||
}
|
||||
}
|
||||
} else if (splitType == 1) {
|
||||
|
@ -3310,7 +3191,7 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
|||
add_theory_aware_branching_info(tester, m_params.m_OverlapTheoryAwarePriority, l_true);
|
||||
} else {
|
||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||
// TODO printCutVar(m, y);
|
||||
TRACE("t_str_detail", {print_cut_var(m, tout); print_cut_var(y, tout);});
|
||||
}
|
||||
}
|
||||
} else if (splitType == -1) {
|
||||
|
@ -3409,7 +3290,7 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
|
|||
add_theory_aware_branching_info(tester, m_params.m_OverlapTheoryAwarePriority, l_true);
|
||||
} else {
|
||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||
// TODO printCutVar(x, n);
|
||||
TRACE("t_str_detail", {print_cut_var(x, tout); print_cut_var(n, tout);});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3572,7 +3453,6 @@ void theory_str::process_concat_eq_type2(expr * concatAst1, expr * concatAst2) {
|
|||
temp1 = varForBreakConcat[key2][0];
|
||||
xorFlag = varForBreakConcat[key2][1];
|
||||
}
|
||||
// TODO refresh xorFlag?
|
||||
refresh_theory_var(temp1);
|
||||
add_nonempty_constraint(temp1);
|
||||
}
|
||||
|
@ -4049,7 +3929,7 @@ void theory_str::process_concat_eq_type3(expr * concatAst1, expr * concatAst2) {
|
|||
add_theory_aware_branching_info(tester, m_params.m_OverlapTheoryAwarePriority, l_true);
|
||||
} else {
|
||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED" << std::endl;);
|
||||
// TODO printCutVar(x, n);
|
||||
TRACE("t_str_detail", {print_cut_var(x, tout); print_cut_var(n, tout);});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4129,7 +4009,7 @@ void theory_str::process_concat_eq_type3(expr * concatAst1, expr * concatAst2) {
|
|||
add_theory_aware_branching_info(tester, m_params.m_OverlapTheoryAwarePriority, l_true);
|
||||
} else {
|
||||
TRACE("t_str", tout << "AVOID LOOP: SKIPPED." << std::endl;);
|
||||
// TODO printCutVAR(x, n)
|
||||
TRACE("t_str_detail", {print_cut_var(x, tout); print_cut_var(n, tout);});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4712,26 +4592,6 @@ void theory_str::unroll_str2reg_constStr(expr * unrollFunc, expr * eqConstStr) {
|
|||
* Return that constant if it is found, and set hasEqcValue to true.
|
||||
* Otherwise, return n, and set hasEqcValue to false.
|
||||
*/
|
||||
/*
|
||||
expr * theory_str::get_eqc_value(expr * n, bool & hasEqcValue) {
|
||||
context & ctx = get_context();
|
||||
// I hope this works
|
||||
ctx.internalize(n, false);
|
||||
enode * nNode = ctx.get_enode(n);
|
||||
enode * eqcNode = nNode;
|
||||
do {
|
||||
app * ast = eqcNode->get_owner();
|
||||
if (is_string(eqcNode)) {
|
||||
hasEqcValue = true;
|
||||
return ast;
|
||||
}
|
||||
eqcNode = eqcNode->get_next();
|
||||
} while (eqcNode != nNode);
|
||||
// not found
|
||||
hasEqcValue = false;
|
||||
return n;
|
||||
}
|
||||
*/
|
||||
|
||||
expr * theory_str::get_eqc_value(expr * n, bool & hasEqcValue) {
|
||||
return z3str2_get_eqc_value(n, hasEqcValue);
|
||||
|
@ -6596,8 +6456,6 @@ void theory_str::solve_concat_eq_str(expr * concat, expr * str) {
|
|||
// check the entries in this map to make sure they're still in scope
|
||||
// before we use them.
|
||||
|
||||
// TODO XOR variables will always show up as "not in scope" because of how we update internal_variable_set
|
||||
|
||||
std::map<std::pair<expr*,expr*>, std::map<int, expr*> >::iterator entry1 = varForBreakConcat.find(key1);
|
||||
std::map<std::pair<expr*,expr*>, std::map<int, expr*> >::iterator entry2 = varForBreakConcat.find(key2);
|
||||
|
||||
|
@ -7409,14 +7267,6 @@ void theory_str::push_scope_eh() {
|
|||
theory::push_scope_eh();
|
||||
m_trail_stack.push_scope();
|
||||
|
||||
// TODO out-of-scope term debugging, see comment in pop_scope_eh()
|
||||
/*
|
||||
context & ctx = get_context();
|
||||
ast_manager & m = get_manager();
|
||||
expr_ref_vector assignments(m);
|
||||
ctx.get_assignments(assignments);
|
||||
*/
|
||||
|
||||
sLevel += 1;
|
||||
TRACE("t_str", tout << "push to " << sLevel << std::endl;);
|
||||
TRACE_CODE(if (is_trace_enabled("t_str_dump_assign_on_scope_change")) { dump_assignments(); });
|
||||
|
@ -9846,7 +9696,6 @@ expr * theory_str::gen_len_test_options(expr * freeVar, expr * indicator, int tr
|
|||
andList.push_back(and_expr);
|
||||
}
|
||||
|
||||
// TODO cache mk_string("more")
|
||||
expr_ref more_option(ctx.mk_eq_atom(indicator, mk_string("more")), m);
|
||||
orList.push_back(more_option);
|
||||
// decrease priority of this option
|
||||
|
@ -10558,8 +10407,6 @@ model_value_proc * theory_str::mk_value(enode * n, model_generator & mg) {
|
|||
return alloc(expr_wrapper_proc, val);
|
||||
} else {
|
||||
TRACE("t_str", tout << "WARNING: failed to find a concrete value, falling back" << std::endl;);
|
||||
// TODO make absolutely sure the reason we can't find a concrete value is because of an unassigned temporary
|
||||
// e.g. for an expression like (Concat X $$_str0)
|
||||
return alloc(expr_wrapper_proc, to_app(mk_string("**UNUSED**")));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue