mirror of
https://github.com/Z3Prover/z3
synced 2025-06-27 08:28:44 +00:00
attempt to clean up out-of-scope variables more, still crashing
This commit is contained in:
parent
c44d49b625
commit
52f0277c99
2 changed files with 48 additions and 6 deletions
|
@ -32,6 +32,8 @@ theory_str::theory_str(ast_manager & m):
|
||||||
sLevel(0),
|
sLevel(0),
|
||||||
tmpStringVarCount(0),
|
tmpStringVarCount(0),
|
||||||
tmpXorVarCount(0),
|
tmpXorVarCount(0),
|
||||||
|
tmpLenTestVarCount(0),
|
||||||
|
tmpValTestVarCount(0),
|
||||||
avoidLoopCut(true),
|
avoidLoopCut(true),
|
||||||
loopDetected(false)
|
loopDetected(false)
|
||||||
{
|
{
|
||||||
|
@ -297,11 +299,14 @@ app * theory_str::mk_int(int n) {
|
||||||
return m_autil.mk_numeral(rational(n), true);
|
return m_autil.mk_numeral(rational(n), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have to work a little bit harder to ensure that all variables we create here are always fresh.
|
||||||
|
|
||||||
expr * theory_str::mk_internal_lenTest_var(expr * node, int lTries) {
|
expr * theory_str::mk_internal_lenTest_var(expr * node, int lTries) {
|
||||||
ast_manager & m = get_manager();
|
ast_manager & m = get_manager();
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "$$_len_" << mk_ismt2_pp(node, m) << "_" << lTries;
|
ss << "$$_len_" << mk_ismt2_pp(node, m) << "_" << lTries << "_" << tmpLenTestVarCount;
|
||||||
|
tmpLenTestVarCount += 1;
|
||||||
std::string name = ss.str();
|
std::string name = ss.str();
|
||||||
return mk_str_var(name);
|
return mk_str_var(name);
|
||||||
|
|
||||||
|
@ -317,7 +322,8 @@ expr * theory_str::mk_internal_lenTest_var(expr * node, int lTries) {
|
||||||
expr * theory_str::mk_internal_valTest_var(expr * node, int len, int vTries) {
|
expr * theory_str::mk_internal_valTest_var(expr * node, int len, int vTries) {
|
||||||
ast_manager & m = get_manager();
|
ast_manager & m = get_manager();
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "$$_val_" << mk_ismt2_pp(node, m) << "_" << len << "_" << vTries;
|
ss << "$$_val_" << mk_ismt2_pp(node, m) << "_" << len << "_" << vTries << "_" << tmpValTestVarCount;
|
||||||
|
tmpValTestVarCount += 1;
|
||||||
std::string name = ss.str();
|
std::string name = ss.str();
|
||||||
return mk_str_var(name);
|
return mk_str_var(name);
|
||||||
|
|
||||||
|
@ -3923,9 +3929,35 @@ expr * theory_str::gen_len_val_options_for_free_var(expr * freeVar, expr * lenTe
|
||||||
ast_manager & m = get_manager();
|
ast_manager & m = get_manager();
|
||||||
|
|
||||||
TRACE("t_str_detail", tout << "gen for free var " << mk_ismt2_pp(freeVar, m) << std::endl;);
|
TRACE("t_str_detail", tout << "gen for free var " << mk_ismt2_pp(freeVar, m) << std::endl;);
|
||||||
// no length assertions for this free variable have ever been added.
|
|
||||||
if (fvar_len_count_map.find(freeVar) == fvar_len_count_map.end()) {
|
|
||||||
|
|
||||||
|
bool map_effectively_empty = false;
|
||||||
|
if (fvar_len_count_map.find(freeVar) == fvar_len_count_map.end()) {
|
||||||
|
TRACE("t_str_detail", tout << "fvar_len_count_map is empty" << std::endl;);
|
||||||
|
map_effectively_empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!map_effectively_empty) {
|
||||||
|
// check whether any entries correspond to variables that went out of scope;
|
||||||
|
// if every entry is out of scope then the map counts as being empty
|
||||||
|
// TODO: maybe remove them from the map instead? either here or in pop_scope_eh()
|
||||||
|
|
||||||
|
// assume empty and find a counterexample
|
||||||
|
map_effectively_empty = true;
|
||||||
|
ptr_vector<expr> indicator_set = fvar_lenTester_map[freeVar];
|
||||||
|
for (ptr_vector<expr>::iterator it = indicator_set.begin(); it != indicator_set.end(); ++it) {
|
||||||
|
expr * indicator = *it;
|
||||||
|
if (internal_variable_set.find(indicator) != internal_variable_set.end()) {
|
||||||
|
TRACE("t_str_detail", tout <<"found active internal variable " << mk_ismt2_pp(indicator, m)
|
||||||
|
<< " in fvar_lenTester_map[freeVar]" << std::endl;);
|
||||||
|
map_effectively_empty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CTRACE("t_str_detail", map_effectively_empty, tout << "all variables in fvar_lenTester_map[freeVar] out of scope" << std::endl;);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map_effectively_empty) {
|
||||||
|
// no length assertions for this free variable have ever been added.
|
||||||
TRACE("t_str_detail", tout << "no length assertions yet" << std::endl;);
|
TRACE("t_str_detail", tout << "no length assertions yet" << std::endl;);
|
||||||
|
|
||||||
fvar_len_count_map[freeVar] = 1;
|
fvar_len_count_map[freeVar] = 1;
|
||||||
|
@ -3934,6 +3966,8 @@ expr * theory_str::gen_len_val_options_for_free_var(expr * freeVar, expr * lenTe
|
||||||
expr * indicator = mk_internal_lenTest_var(freeVar, testNum);
|
expr * indicator = mk_internal_lenTest_var(freeVar, testNum);
|
||||||
SASSERT(indicator != NULL);
|
SASSERT(indicator != NULL);
|
||||||
|
|
||||||
|
// since the map is "effectively empty", we can remove those variables that have left scope...
|
||||||
|
fvar_lenTester_map[freeVar].shrink(0);
|
||||||
fvar_lenTester_map[freeVar].push_back(indicator);
|
fvar_lenTester_map[freeVar].push_back(indicator);
|
||||||
lenTester_fvar_map[indicator] = freeVar;
|
lenTester_fvar_map[indicator] = freeVar;
|
||||||
|
|
||||||
|
@ -3941,7 +3975,8 @@ expr * theory_str::gen_len_val_options_for_free_var(expr * freeVar, expr * lenTe
|
||||||
SASSERT(lenTestAssert != NULL);
|
SASSERT(lenTestAssert != NULL);
|
||||||
return lenTestAssert;
|
return lenTestAssert;
|
||||||
} else {
|
} else {
|
||||||
TRACE("t_str_detail", tout << "found previous length assertions" << std::endl;);
|
TRACE("t_str_detail", tout << "found previous in-scope length assertions" << std::endl;);
|
||||||
|
|
||||||
expr * effectiveLenInd = NULL;
|
expr * effectiveLenInd = NULL;
|
||||||
std::string effectiveLenIndiStr = "";
|
std::string effectiveLenIndiStr = "";
|
||||||
int lenTesterCount = (int) fvar_lenTester_map[freeVar].size();
|
int lenTesterCount = (int) fvar_lenTester_map[freeVar].size();
|
||||||
|
@ -3949,6 +3984,11 @@ expr * theory_str::gen_len_val_options_for_free_var(expr * freeVar, expr * lenTe
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < lenTesterCount; ++i) {
|
for (; i < lenTesterCount; ++i) {
|
||||||
expr * len_indicator_pre = fvar_lenTester_map[freeVar][i];
|
expr * len_indicator_pre = fvar_lenTester_map[freeVar][i];
|
||||||
|
// check whether this is in scope as well
|
||||||
|
if (internal_variable_set.find(len_indicator_pre) == internal_variable_set.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool indicatorHasEqcValue = false;
|
bool indicatorHasEqcValue = false;
|
||||||
expr * len_indicator_value = get_eqc_value(len_indicator_pre, indicatorHasEqcValue);
|
expr * len_indicator_value = get_eqc_value(len_indicator_pre, indicatorHasEqcValue);
|
||||||
TRACE("t_str_detail", tout << "length indicator " << mk_ismt2_pp(len_indicator_pre, m) <<
|
TRACE("t_str_detail", tout << "length indicator " << mk_ismt2_pp(len_indicator_pre, m) <<
|
||||||
|
|
|
@ -63,9 +63,9 @@ namespace smt {
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
bool search_started;
|
bool search_started;
|
||||||
int sLevel;
|
|
||||||
arith_util m_autil;
|
arith_util m_autil;
|
||||||
str_util m_strutil;
|
str_util m_strutil;
|
||||||
|
int sLevel;
|
||||||
|
|
||||||
str_value_factory * m_factory;
|
str_value_factory * m_factory;
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ namespace smt {
|
||||||
|
|
||||||
int tmpStringVarCount;
|
int tmpStringVarCount;
|
||||||
int tmpXorVarCount;
|
int tmpXorVarCount;
|
||||||
|
int tmpLenTestVarCount;
|
||||||
|
int tmpValTestVarCount;
|
||||||
std::map<std::pair<expr*, expr*>, std::map<int, expr*> > varForBreakConcat;
|
std::map<std::pair<expr*, expr*>, std::map<int, expr*> > varForBreakConcat;
|
||||||
|
|
||||||
bool avoidLoopCut;
|
bool avoidLoopCut;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue