3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-27 22:47:55 +00:00

Reorganizing the code

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-20 19:54:08 -07:00
parent 8b70f0b833
commit d8cd3fc3ab
36 changed files with 261 additions and 429 deletions

94
src/ast/expr_map.cpp Normal file
View file

@ -0,0 +1,94 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
expr_map.cpp
Abstract:
Mapping from expressions to expressions + proofs. This mapping
is used to cache simplification results.
For every entry [e1->(e2, p)] we have that p is a proof that (= e1 e2).
Author:
Leonardo (leonardo) 2008-01-03
Notes:
--*/
#include"expr_map.h"
#include"dec_ref_util.h"
expr_map::expr_map(ast_manager & m):
m_manager(m),
m_store_proofs(m.proofs_enabled()) {
}
expr_map::expr_map(ast_manager & m, bool store_proofs):
m_manager(m),
m_store_proofs(store_proofs) {
}
expr_map::~expr_map() {
reset();
}
void expr_map::insert(expr * k, expr * d, proof * p) {
m_manager.inc_ref(d);
obj_map<expr, expr*>::obj_map_entry * entry = m_expr2expr.find_core(k);
if (entry != 0) {
m_manager.dec_ref(entry->get_data().m_value);
entry->get_data().m_value = d;
if (m_store_proofs) {
m_manager.inc_ref(p);
obj_map<expr, proof*>::obj_map_entry * entry_pr = m_expr2pr.find_core(k);
SASSERT(entry_pr != 0);
m_manager.dec_ref(entry_pr->get_data().m_value);
entry_pr->get_data().m_value = p;
}
}
else {
m_manager.inc_ref(k);
m_expr2expr.insert(k, d);
if (m_store_proofs) {
m_manager.inc_ref(p);
m_expr2pr.insert(k, p);
}
}
}
void expr_map::get(expr * k, expr * & d, proof * & p) const {
if (m_expr2expr.find(k, d)) {
p = 0;
if (m_store_proofs)
m_expr2pr.find(k, p);
}
}
void expr_map::erase(expr * k) {
expr * v;
if (m_expr2expr.find(k, v)) {
m_expr2expr.erase(k);
m_manager.dec_ref(v);
if (m_store_proofs) {
proof * pr = 0;
m_expr2pr.find(k, pr);
m_expr2pr.erase(k);
m_manager.dec_ref(pr);
}
m_manager.dec_ref(k);
}
}
void expr_map::reset() {
dec_ref_values(m_manager, m_expr2pr);
dec_ref_key_values(m_manager, m_expr2expr);
}
void expr_map::flush() {
reset();
m_expr2expr.finalize();
m_expr2pr.finalize();
}

49
src/ast/expr_map.h Normal file
View file

@ -0,0 +1,49 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
expr_map.h
Abstract:
Mapping from expressions to expressions + proofs. This mapping
is used to cache simplification results.
For every entry [e1->(e2, p)] we have that p is a proof that (= e1 e2).
Author:
Leonardo (leonardo) 2008-01-03
Notes:
--*/
#ifndef _EXPR_MAP_H_
#define _EXPR_MAP_H_
#include"ast.h"
#include"obj_hashtable.h"
/**
\brief Map from expressions to expressions+proofs.
When proof production is disabled, no extra space is used.
*/
class expr_map {
ast_manager & m_manager;
bool m_store_proofs;
obj_map<expr, expr*> m_expr2expr;
obj_map<expr, proof*> m_expr2pr;
public:
expr_map(ast_manager & m);
expr_map(ast_manager & m, bool store_proofs);
~expr_map();
void insert(expr * k, expr * d, proof * p);
bool contains(expr * k) const { return m_expr2expr.contains(k); }
void get(expr * k, expr * & d, proof * & p) const;
void erase(expr * k);
void reset();
void flush();
};
#endif

View file

@ -0,0 +1,225 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
func_decl_dependencies.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2010-12-15.
Revision History:
--*/
#include"func_decl_dependencies.h"
#include"for_each_expr.h"
#include"ast_util.h"
struct collect_dependencies_proc {
ast_manager & m_manager;
func_decl_set & m_set;
bool m_ng_only; // collect only declarations in non ground expressions
collect_dependencies_proc(ast_manager & m, func_decl_set & s, bool ng_only):
m_manager(m),
m_set(s),
m_ng_only(ng_only) {}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
// We do not need to track dependencies on constants ...
if (n->get_num_args()==0)
return;
if (m_ng_only && is_ground(n))
return;
// ... and interpreted function symbols
func_decl * d = n->get_decl();
if (d->get_family_id() == null_family_id) {
m_set.insert(d);
}
}
};
void collect_func_decls(ast_manager & m, expr * n, func_decl_set & r, bool ng_only) {
collect_dependencies_proc proc(m, r, ng_only);
for_each_expr(proc, n);
}
void func_decl_dependencies::reset() {
dependency_graph::iterator it = m_deps.begin();
dependency_graph::iterator end = m_deps.end();
for (; it != end; ++it) {
func_decl * f = (*it).m_key;
func_decl_set * s = (*it).m_value;
m_manager.dec_ref(f);
dec_ref(m_manager, *s);
dealloc(s);
}
m_deps.reset();
}
void func_decl_dependencies::collect_func_decls(expr * n, func_decl_set * s) {
::collect_func_decls(m_manager, n, *s, false);
}
void func_decl_dependencies::collect_ng_func_decls(expr * n, func_decl_set * s) {
::collect_func_decls(m_manager, n, *s, true);
}
/**
\brief Functor for finding cycles in macro definitions
*/
class func_decl_dependencies::top_sort {
enum color { OPEN, IN_PROGRESS, CLOSED };
ast_manager & m_manager;
dependency_graph & m_deps;
typedef obj_map<func_decl, color> color_map;
color_map m_colors;
ptr_vector<func_decl> m_todo;
func_decl_set * definition(func_decl * f) const {
func_decl_set * r = 0;
m_deps.find(f, r);
return r;
}
color get_color(func_decl * f) const {
if (!f)
return CLOSED;
color_map::iterator it = m_colors.find_iterator(f);
if (it != m_colors.end())
return it->m_value;
return OPEN;
}
void set_color(func_decl * f, color c) {
m_colors.insert(f, c);
}
void visit(func_decl * f, bool & visited) {
if (get_color(f) != CLOSED) {
m_todo.push_back(f);
visited = false;
}
}
bool visit_children(func_decl * f) {
func_decl_set * def = definition(f);
if (!def)
return true;
bool visited = true;
func_decl_set::iterator it = def->begin();
func_decl_set::iterator end = def->end();
for (; it != end; ++it) {
visit(*it, visited);
}
return visited;
}
bool all_children_closed(func_decl * f) const {
func_decl_set * def = definition(f);
if (!def)
return true;
func_decl_set::iterator it = def->begin();
func_decl_set::iterator end = def->end();
for (; it != end; ++it) {
if (get_color(*it) != CLOSED)
return false;
}
return true;
}
/**
\brief Return \c true if a cycle is detected.
*/
bool main_loop(func_decl * f) {
if (get_color(f) == CLOSED)
return false;
m_todo.push_back(f);
while (!m_todo.empty()) {
func_decl * f = m_todo.back();
switch (get_color(f)) {
case CLOSED:
m_todo.pop_back();
break;
case OPEN:
set_color(f, IN_PROGRESS);
if (visit_children(f)) {
SASSERT(m_todo.back() == f);
m_todo.pop_back();
set_color(f, CLOSED);
}
break;
case IN_PROGRESS:
if (all_children_closed(f)) {
SASSERT(m_todo.back() == f);
set_color(f, CLOSED);
} else {
m_todo.reset();
return true;
}
break;
default:
UNREACHABLE();
}
}
return false;
}
public:
top_sort(ast_manager & m, dependency_graph & deps):m_manager(m), m_deps(deps) {}
bool operator()(func_decl * new_decl) {
// [Leo]: It is not trivial to reuse m_colors between different calls since we are update the graph.
// To implement this optimization, we need an incremental topological sort algorithm.
// The trick of saving the dependencies will save a lot of time. So, I don't think we really
// need a incremental top-sort algo.
m_colors.reset();
return main_loop(new_decl);
}
};
bool func_decl_dependencies::insert(func_decl * f, func_decl_set * s) {
if (m_deps.contains(f)) {
dealloc(s);
return false;
}
m_deps.insert(f, s);
top_sort cycle_detector(m_manager, m_deps);
if (cycle_detector(f)) {
m_deps.erase(f);
dealloc(s);
return false;
}
m_manager.inc_ref(f);
inc_ref(m_manager, *s);
return true;
}
void func_decl_dependencies::erase(func_decl * f) {
func_decl_set * s = 0;
if (m_deps.find(f, s)) {
m_manager.dec_ref(f);
dec_ref(m_manager, *s);
m_deps.erase(f);
dealloc(s);
}
}
void func_decl_dependencies::display(std::ostream & out) {
// TODO
}

View file

@ -0,0 +1,110 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
func_decl_dependencies.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2010-12-15.
Revision History:
--*/
#ifndef _FUNC_DECL_DEPENDENCIES_H_
#define _FUNC_DECL_DEPENDENCIES_H_
#include"ast.h"
#include"obj_hashtable.h"
// Set of dependencies
typedef obj_hashtable<func_decl> func_decl_set;
/**
\brief Collect uninterpreted function declarations (with arity > 0) occurring in \c n.
*/
void collect_func_decls(ast_manager & m, expr * n, func_decl_set & r, bool ng_only = false);
/**
\brief Auxiliary data-structure used for tracking dependencies between function declarations.
The following pattern of use is expected:
func_decl_dependencies & dm;
func_decl_set * S = dm.mk_func_decl_set();
dm.collect_func_decls(t_1, S);
...
dm.collect_func_decls(t_n, S);
dm.insert(f, S);
*/
class func_decl_dependencies {
typedef obj_map<func_decl, func_decl_set *> dependency_graph;
ast_manager & m_manager;
dependency_graph m_deps;
class top_sort;
public:
func_decl_dependencies(ast_manager & m):m_manager(m) {}
~func_decl_dependencies() {
reset();
}
void reset();
/**
\brief Create a dependecy set.
This set should be populated using #collect_func_decls.
After populating the set, it must be used as an argument for the #insert method.
\remark The manager owns the set.
\warning Failure to call #insert will produce a memory leak.
*/
func_decl_set * mk_func_decl_set() { return alloc(func_decl_set); }
/**
\brief Store the uninterpreted function declarations used in \c n into \c s.
*/
void collect_func_decls(expr * n, func_decl_set * s);
/**
\brief Store the uninterpreted function declarations (in non ground terms) used in \c n into \c s.
*/
void collect_ng_func_decls(expr * n, func_decl_set * s);
/**
\brief Insert \c f in the manager with the given set of dependencies.
The insertion succeeds iff
1- no cycle is created between the new entry and
the already existing dependencies.
2- \c f was not already inserted into the manager.
Return false in case of failure.
\remark The manager is the owner of the dependency sets.
*/
bool insert(func_decl * f, func_decl_set * s);
/**
\brief Return true if \c f is registered in this manager.
*/
bool contains(func_decl * f) const { return m_deps.contains(f); }
func_decl_set * get_dependencies(func_decl * f) const { func_decl_set * r = 0; m_deps.find(f, r); return r; }
/**
\brief Erase \c f (and its dependencies) from the manager.
*/
void erase(func_decl * f);
void display(std::ostream & out);
};
#endif

105
src/ast/used_symbols.h Normal file
View file

@ -0,0 +1,105 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
used_symbols.h
Abstract:
Collect the symbols used in an expression.
Author:
Leonardo de Moura (leonardo) 2011-01-11.
Revision History:
--*/
#ifndef _USED_SYMBOLS_H_
#define _USED_SYMBOLS_H_
#include"ast.h"
#include"hashtable.h"
#include"obj_hashtable.h"
struct do_nothing_rename_proc {
symbol operator()(symbol const & s) const { return s; }
};
/**
\brief Functor for collecting the symbols used in an expression.
*/
template<typename RENAME_PROC=do_nothing_rename_proc>
class used_symbols : public RENAME_PROC {
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
symbol_set m_used;
obj_hashtable<expr> m_visited;
ptr_vector<expr> m_todo;
void found(symbol const & s) { m_used.insert(RENAME_PROC::operator()(s)); }
void visit(expr * n) {
if (!m_visited.contains(n)) {
m_visited.insert(n);
m_todo.push_back(n);
}
}
public:
used_symbols(RENAME_PROC const & p = RENAME_PROC()):
RENAME_PROC(p) {
}
void operator()(expr * n, bool ignore_quantifiers = false) {
m_visited.reset();
m_used.reset();
m_todo.reset();
visit(n);
while (!m_todo.empty()) {
n = m_todo.back();
m_todo.pop_back();
unsigned j;
switch (n->get_kind()) {
case AST_APP:
found(to_app(n)->get_decl()->get_name());
j = to_app(n)->get_num_args();
while (j > 0) {
--j;
visit(to_app(n)->get_arg(j));
}
break;
case AST_QUANTIFIER:
if (!ignore_quantifiers) {
found(to_quantifier(n)->get_qid());
unsigned num_decls = to_quantifier(n)->get_num_decls();
for (unsigned i = 0; i < num_decls; i++)
found(to_quantifier(n)->get_decl_name(i));
unsigned num_pats = to_quantifier(n)->get_num_patterns();
for (unsigned i = 0; i < num_pats; i++)
visit(to_quantifier(n)->get_pattern(i));
unsigned num_no_pats = to_quantifier(n)->get_num_no_patterns();
for (unsigned i = 0; i < num_no_pats; i++)
visit(to_quantifier(n)->get_no_pattern(i));
visit(to_quantifier(n)->get_expr());
}
break;
default:
break;
}
}
}
bool contains(symbol const & s) const { return m_used.contains(RENAME_PROC::operator()(s)); }
bool contains_core(symbol const & s) const { return m_used.contains(s); }
void insert(symbol const & s) { m_used.insert(RENAME_PROC::operator()(s)); }
void insert_core(symbol const & s) { m_used.insert(s); }
void erase_core(symbol const & s) { m_used.erase(s); }
};
#endif /* _USED_SYMBOLS_H_ */