mirror of
https://github.com/Z3Prover/z3
synced 2026-05-24 19:06:21 +00:00
Extract handle_empty_side helper in seq_nielsen to eliminate duplicate code
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
da1b61cd44
commit
2eebe57467
2 changed files with 38 additions and 42 deletions
|
|
@ -514,6 +514,33 @@ namespace seq {
|
||||||
// nielsen_node: simplify_and_init
|
// nielsen_node: simplify_and_init
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool nielsen_node::handle_empty_side(euf::sgraph& sg, euf::snode* non_empty_side,
|
||||||
|
dep_tracker const& dep, bool& changed) {
|
||||||
|
euf::snode_vector tokens;
|
||||||
|
non_empty_side->collect_tokens(tokens);
|
||||||
|
bool all_vars_or_opaque = true;
|
||||||
|
bool has_char = false;
|
||||||
|
for (euf::snode* t : tokens) {
|
||||||
|
if (t->is_char()) has_char = true;
|
||||||
|
else if (!t->is_var() && t->kind() != euf::snode_kind::s_other) {
|
||||||
|
all_vars_or_opaque = false; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_char || !all_vars_or_opaque) {
|
||||||
|
m_is_general_conflict = true;
|
||||||
|
m_reason = backtrack_reason::symbol_clash;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (euf::snode* t : tokens) {
|
||||||
|
if (t->is_var()) {
|
||||||
|
nielsen_subst s(t, sg.mk_empty(), dep);
|
||||||
|
apply_subst(sg, s);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
simplify_result nielsen_node::simplify_and_init(nielsen_graph& g) {
|
simplify_result nielsen_node::simplify_and_init(nielsen_graph& g) {
|
||||||
euf::sgraph& sg = g.sg();
|
euf::sgraph& sg = g.sg();
|
||||||
bool changed = true;
|
bool changed = true;
|
||||||
|
|
@ -556,53 +583,13 @@ namespace seq {
|
||||||
|
|
||||||
// one side empty, the other not empty => conflict or substitution
|
// one side empty, the other not empty => conflict or substitution
|
||||||
if (eq.m_lhs->is_empty() && !eq.m_rhs->is_empty()) {
|
if (eq.m_lhs->is_empty() && !eq.m_rhs->is_empty()) {
|
||||||
euf::snode_vector tokens;
|
if (handle_empty_side(sg, eq.m_rhs, eq.m_dep, changed))
|
||||||
eq.m_rhs->collect_tokens(tokens);
|
|
||||||
bool all_vars_or_opaque = true;
|
|
||||||
bool has_char = false;
|
|
||||||
for (euf::snode* t : tokens) {
|
|
||||||
if (t->is_char()) has_char = true;
|
|
||||||
else if (!t->is_var() && t->kind() != euf::snode_kind::s_other) {
|
|
||||||
all_vars_or_opaque = false; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (has_char || !all_vars_or_opaque) {
|
|
||||||
m_is_general_conflict = true;
|
|
||||||
m_reason = backtrack_reason::symbol_clash;
|
|
||||||
return simplify_result::conflict;
|
return simplify_result::conflict;
|
||||||
}
|
|
||||||
for (euf::snode* t : tokens) {
|
|
||||||
if (t->is_var()) {
|
|
||||||
nielsen_subst s(t, sg.mk_empty(), eq.m_dep);
|
|
||||||
apply_subst(sg, s);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (eq.m_rhs->is_empty() && !eq.m_lhs->is_empty()) {
|
if (eq.m_rhs->is_empty() && !eq.m_lhs->is_empty()) {
|
||||||
euf::snode_vector tokens;
|
if (handle_empty_side(sg, eq.m_lhs, eq.m_dep, changed))
|
||||||
eq.m_lhs->collect_tokens(tokens);
|
|
||||||
bool all_vars_or_opaque = true;
|
|
||||||
bool has_char = false;
|
|
||||||
for (euf::snode* t : tokens) {
|
|
||||||
if (t->is_char()) has_char = true;
|
|
||||||
else if (!t->is_var() && t->kind() != euf::snode_kind::s_other) {
|
|
||||||
all_vars_or_opaque = false; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (has_char || !all_vars_or_opaque) {
|
|
||||||
m_is_general_conflict = true;
|
|
||||||
m_reason = backtrack_reason::symbol_clash;
|
|
||||||
return simplify_result::conflict;
|
return simplify_result::conflict;
|
||||||
}
|
|
||||||
for (euf::snode* t : tokens) {
|
|
||||||
if (t->is_var()) {
|
|
||||||
nielsen_subst s(t, sg.mk_empty(), eq.m_dep);
|
|
||||||
apply_subst(sg, s);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -502,6 +502,15 @@ namespace seq {
|
||||||
// render constraint set as an HTML fragment for DOT node labels.
|
// render constraint set as an HTML fragment for DOT node labels.
|
||||||
// mirrors ZIPT's NielsenNode.ToHtmlString()
|
// mirrors ZIPT's NielsenNode.ToHtmlString()
|
||||||
std::ostream& display_html(std::ostream& out, ast_manager& m) const;
|
std::ostream& display_html(std::ostream& out, ast_manager& m) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helper: handle one empty vs one non-empty side of a string equality.
|
||||||
|
// Collects tokens from non_empty_side; if any token causes a conflict
|
||||||
|
// (is a concrete character or an unexpected kind), sets conflict flags
|
||||||
|
// and returns true. Otherwise substitutes all variables to empty,
|
||||||
|
// sets changed=true, and returns false.
|
||||||
|
bool handle_empty_side(euf::sgraph& sg, euf::snode* non_empty_side,
|
||||||
|
dep_tracker const& dep, bool& changed);
|
||||||
};
|
};
|
||||||
|
|
||||||
// search statistics collected during Nielsen graph solving
|
// search statistics collected during Nielsen graph solving
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue