mirror of
https://github.com/Z3Prover/z3
synced 2025-04-10 03:07:07 +00:00
141 lines
3.4 KiB
C++
141 lines
3.4 KiB
C++
/*++
|
|
Copyright (c) 2011 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
shared_occs.cpp
|
|
|
|
Abstract:
|
|
|
|
Functor for computing the shared subterms in a given
|
|
term.
|
|
|
|
Author:
|
|
|
|
Leonardo de Moura (leonardo) 2011-04-01.
|
|
|
|
Revision History:
|
|
--*/
|
|
#include"shared_occs.h"
|
|
#include"ast_smt2_pp.h"
|
|
#include"ref_util.h"
|
|
|
|
inline void shared_occs::insert(expr * t) {
|
|
obj_hashtable<expr>::entry * dummy;
|
|
if (m_shared.insert_if_not_there_core(t, dummy))
|
|
m.inc_ref(t);
|
|
}
|
|
|
|
void shared_occs::reset() {
|
|
dec_ref_collection_values(m, m_shared);
|
|
m_shared.reset();
|
|
}
|
|
|
|
void shared_occs::cleanup() {
|
|
reset();
|
|
m_shared.finalize();
|
|
m_stack.finalize();
|
|
}
|
|
|
|
shared_occs::~shared_occs() {
|
|
reset();
|
|
}
|
|
|
|
inline bool shared_occs::process(expr * t, shared_occs_mark & visited) {
|
|
switch (t->get_kind()) {
|
|
case AST_APP: {
|
|
unsigned num_args = to_app(t)->get_num_args();
|
|
if (t->get_ref_count() > 1 && (m_track_atomic || num_args > 0)) {
|
|
if (visited.is_marked(t)) {
|
|
insert(t);
|
|
return true;
|
|
}
|
|
visited.mark(t);
|
|
}
|
|
if (num_args == 0)
|
|
return true; // done with t
|
|
m_stack.push_back(frame(t, 0)); // need to create frame if num_args > 0
|
|
return false;
|
|
}
|
|
case AST_VAR:
|
|
if (m_track_atomic && t->get_ref_count() > 1) {
|
|
if (visited.is_marked(t))
|
|
insert(t);
|
|
else
|
|
visited.mark(t);
|
|
}
|
|
return true; // done with t
|
|
case AST_QUANTIFIER:
|
|
if (t->get_ref_count() > 1) {
|
|
if (visited.is_marked(t)) {
|
|
insert(t);
|
|
return true; // done with t
|
|
}
|
|
visited.mark(t);
|
|
}
|
|
if (!m_visit_quantifiers)
|
|
return true;
|
|
m_stack.push_back(frame(t, 0));
|
|
return false;
|
|
default:
|
|
UNREACHABLE();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void shared_occs::operator()(expr * t, shared_occs_mark & visited) {
|
|
SASSERT(m_stack.empty());
|
|
if (process(t, visited)) {
|
|
return;
|
|
}
|
|
SASSERT(!m_stack.empty());
|
|
while (!m_stack.empty()) {
|
|
start:
|
|
frame & fr = m_stack.back();
|
|
expr * curr = fr.first;
|
|
switch (curr->get_kind()) {
|
|
case AST_APP: {
|
|
unsigned num_args = to_app(curr)->get_num_args();
|
|
while (fr.second < num_args) {
|
|
expr * arg = to_app(curr)->get_arg(fr.second);
|
|
fr.second++;
|
|
if (!process(arg, visited))
|
|
goto start;
|
|
}
|
|
break;
|
|
}
|
|
case AST_QUANTIFIER: {
|
|
SASSERT(m_visit_quantifiers);
|
|
unsigned num_children = m_visit_patterns ? to_quantifier(curr)->get_num_children() : 1;
|
|
while (fr.second < num_children) {
|
|
expr * child = to_quantifier(curr)->get_child(fr.second);
|
|
fr.second++;
|
|
if (!process(child, visited))
|
|
goto start;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
UNREACHABLE();
|
|
break;
|
|
}
|
|
m_stack.pop_back();
|
|
}
|
|
}
|
|
|
|
|
|
void shared_occs::operator()(expr * t) {
|
|
SASSERT(m_stack.empty());
|
|
shared_occs_mark visited;
|
|
reset();
|
|
operator()(t, visited);
|
|
}
|
|
|
|
void shared_occs::display(std::ostream & out, ast_manager & m) const {
|
|
iterator it = begin_shared();
|
|
iterator end = end_shared();
|
|
for (; it != end; ++it) {
|
|
out << mk_ismt2_pp(*it, m) << "\n";
|
|
}
|
|
}
|