3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-09-30 21:19:29 +00:00

Reorganizing code base

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-20 16:33:01 -07:00
parent 9a84cba6c9
commit ded42feeb6
62 changed files with 4 additions and 115 deletions

224
src/ast/act_cache.cpp Normal file
View file

@ -0,0 +1,224 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
act_cache.cpp
Abstract:
expr -> expr activity cache
It maintains at most N unused entries
Author:
Leonardo (leonardo) 2011-04-12
Notes:
--*/
#include"act_cache.h"
#define MIN_MAX_UNUSED 1024
#define INITIAL_CAPACITY 128
/*
This cache is a mapping from expr -> tagged expressions
A tagged expression is essentially a pair (expr, flag)
Thus, an entry
t -> (s, 0)
maps the key t to value s, and says that key t was never accessed.
That is, client code never executed find(t)
Similarly, an entry
t -> (s, 1)
also maps the key t to value s, but signs that key t was already accessed
by client code.
When a new key/value pair is inserted the flag is 0.
The flag is set to 1 after the key is accessed.
The number of unused entries (m_unused) is equal to the number of entries
of the form
t -> (s, 0)
That is, it is the number of keys that were never accessed by cliend code.
The cache maintains at most m_max_unused entries.
When the maximum number of unused entries exceeds m_max_unused, then
the cache will delete the oldest unused entry.
*/
/**
m_queue stores the recently added keys.
The queue is implemented as pair: m_queue (vector), m_qhead (unsigned).
The "active" part of m_queue is the range [m_qhead, m_queue.size())
The "inactive" part [0, m_qhead) contains keys that were already used by client code.
This procedure, deletes the inactive part, and makes m_qhead == 0.
*/
void act_cache::compress_queue() {
SASSERT(m_qhead > 0);
unsigned sz = m_queue.size();
unsigned j = 0;
for (unsigned i = m_qhead; i < sz; i++, j++) {
m_queue[j] = m_queue[i];
}
m_queue.shrink(j);
m_qhead = 0;
}
void act_cache::init() {
if (m_max_unused < MIN_MAX_UNUSED)
m_max_unused = MIN_MAX_UNUSED;
m_unused = 0;
m_qhead = 0;
}
void act_cache::dec_refs() {
map::iterator it = m_table.begin();
map::iterator end = m_table.end();
for (; it != end; ++it) {
m_manager.dec_ref((*it).m_key);
m_manager.dec_ref(UNTAG(expr*, (*it).m_value));
}
}
act_cache::act_cache(ast_manager & m):
m_manager(m),
m_max_unused(m.get_num_asts()) {
init();
}
act_cache::act_cache(ast_manager & m, unsigned max_unused):
m_manager(m),
m_max_unused(max_unused) {
init();
}
act_cache::~act_cache() {
dec_refs();
}
/**
\brief Search m_queue from [m_qhead, m_queue.size()) until it finds
an unused key. That is a key associated with an entry
key -> (value, 0)
*/
void act_cache::del_unused() {
unsigned sz = m_queue.size();
while (m_qhead < sz) {
expr * k = m_queue[m_qhead];
m_qhead++;
SASSERT(m_table.contains(k));
map::key_value * entry = m_table.find_core(k);
SASSERT(entry);
if (GET_TAG(entry->m_value) == 0) {
// Key k was never accessed by client code.
// That is, find(k) was never executed by client code.
m_unused--;
expr * v = entry->m_value;
m_table.erase(k);
m_manager.dec_ref(k);
m_manager.dec_ref(v);
break;
}
}
if (m_qhead == sz) {
// The "active" part of the queue is empty.
// So, we perform a "cheap" compress.
m_queue.reset();
m_qhead = 0;
}
else if (m_qhead > m_max_unused) {
compress_queue();
}
}
/**
\brief Insert a new entry k -> v into the cache.
*/
void act_cache::insert(expr * k, expr * v) {
SASSERT(k);
if (m_unused >= m_max_unused)
del_unused();
expr * dummy = reinterpret_cast<expr*>(1);
map::key_value & entry = m_table.insert_if_not_there(k, dummy);
#if 0
unsigned static counter = 0;
counter++;
if (counter % 100000 == 0)
verbose_stream() << "[act-cache] counter: " << counter << " used_slots: " << m_table.used_slots() << " capacity: " << m_table.capacity() << " size: " << m_table.size() << " collisions: " << m_table.collisions() << "\n";
#endif
#ifdef Z3DEBUG
unsigned expected_tag;
#endif
if (entry.m_value == dummy) {
// new entry;
m_manager.inc_ref(k);
m_manager.inc_ref(v);
entry.m_value = v;
m_queue.push_back(k);
m_unused++;
DEBUG_CODE(expected_tag = 0;); // new entry
}
else if (UNTAG(expr*, entry.m_value) == v) {
// already there
DEBUG_CODE(expected_tag = GET_TAG(entry.m_value););
}
else {
// replacing old entry
m_manager.inc_ref(v);
m_manager.dec_ref(UNTAG(expr*, entry.m_value));
entry.m_value = v;
SASSERT(GET_TAG(entry.m_value) == 0);
// replaced old entry, and reset the tag.
DEBUG_CODE(expected_tag = 0;);
}
DEBUG_CODE({
expr * v2;
SASSERT(m_table.find(k, v2));
SASSERT(v == UNTAG(expr*, v2));
SASSERT(expected_tag == GET_TAG(v2));
});
}
/**
\brief Search for key k in the cache.
If entry k -> (v, tag) is found, we set tag to 1.
*/
expr * act_cache::find(expr * k) {
map::key_value * entry = m_table.find_core(k);
if (entry == 0)
return 0;
if (GET_TAG(entry->m_value) == 0) {
entry->m_value = TAG(expr*, entry->m_value, 1);
SASSERT(GET_TAG(entry->m_value) == 1);
SASSERT(m_unused > 0);
m_unused--;
DEBUG_CODE({
expr * v;
SASSERT(m_table.find(k, v));
SASSERT(GET_TAG(v) == 1);
});
}
return UNTAG(expr*, entry->m_value);
}
void act_cache::reset() {
dec_refs();
m_table.reset();
m_queue.reset();
m_unused = 0;
m_qhead = 0;
}
void act_cache::cleanup() {
dec_refs();
m_table.finalize();
m_queue.finalize();
m_unused = 0;
m_qhead = 0;
}
bool act_cache::check_invariant() const {
return true;
}

56
src/ast/act_cache.h Normal file
View file

@ -0,0 +1,56 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
act_cache.h
Abstract:
expr -> expr activity cache
It maintains at most N unused entries
Author:
Leonardo (leonardo) 2011-04-12
Notes:
--*/
#ifndef _ACT_CACHE_H_
#define _ACT_CACHE_H_
#include"ast.h"
#include"obj_hashtable.h"
#include"chashtable.h"
class act_cache {
ast_manager & m_manager;
typedef cmap<expr*, expr*, obj_ptr_hash<expr>, default_eq<expr*> > map;
map m_table;
ptr_vector<expr> m_queue; // recently created queue
unsigned m_qhead;
unsigned m_unused;
unsigned m_max_unused;
void compress_queue();
void init();
void dec_refs();
void del_unused();
public:
act_cache(ast_manager & m);
act_cache(ast_manager & m, unsigned max_unused);
~act_cache();
void insert(expr * k, expr * v);
expr * find(expr * k);
void reset();
void cleanup();
unsigned size() const { return m_table.size(); }
unsigned capacity() const { return m_table.capacity(); }
bool empty() const { return m_table.empty(); }
bool check_invariant() const;
};
#endif

353
src/ast/ast_dag_pp.cpp Normal file
View file

@ -0,0 +1,353 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
ast_dag_pp.cpp
Abstract:
AST low level pretty printer.
Author:
Leonardo de Moura (leonardo) 2006-10-19.
Nikolaj Bjorner (nbjorner) 2007-07-17
Revision History:
--*/
#include<iostream>
#include"for_each_ast.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"ast_pp.h"
class dag_printer {
ast_manager& m_manager;
std::ostream & m_out;
ast_mark& m_mark;
bool m_initialized;
svector<symbol> m_names;
family_id m_basic_fid;
family_id m_bv_fid;
family_id m_arith_fid;
family_id m_array_fid;
arith_util m_arith;
bv_util m_bv;
bool m_enable_shortcut;
void process_ast(ast* a) {
for_each_ast(*this, m_mark, a);
}
void process_info(decl_info* info) {
if (!info) {
return;
}
unsigned num_params = info->get_num_parameters();
for (unsigned i = 0; i < num_params; ++i) {
parameter const& p = info->get_parameter(i);
if (p.is_ast() && !m_mark.is_marked(p.get_ast())) {
process_ast(p.get_ast());
}
}
}
template<typename T>
void display_children(unsigned num_children, T * const * children) {
for (unsigned i = 0; i < num_children; i++) {
display_node_id(children[i]);
}
}
void display_node_id(ast* n) {
unsigned id = n->get_id();
switch(n->get_kind()) {
case AST_FUNC_DECL:
case AST_SORT:
m_out << "$d" << (id - (1 << 31)) << " ";
break;
default:
m_out << "$" << id << " ";
break;
}
}
void display_parameter(parameter const& p)
{
if (p.is_int()) {
m_out << p.get_int() << " ";
}
else if (p.is_ast()) {
SASSERT(p.is_ast());
display_node_id(p.get_ast());
}
else if (p.is_rational()) {
m_out << p.get_rational() << " ";
}
else if (p.is_symbol()) {
display_symbol(p.get_symbol());
}
else {
UNREACHABLE();
}
}
// Display:
// App name [ parameters] arguments
//
void display_builtin(app* n) {
func_decl* d = n->get_decl();
unsigned num_params = d->get_num_parameters();
m_out << "App ";
display_node_id(n);
display_symbol(d->get_name());
if (num_params > 0) {
m_out << "[ ";
for (unsigned i = 0; i < num_params; ++i) {
display_parameter(d->get_parameter(i));
}
m_out << "] ";
}
display_children(n->get_num_args(), n->get_args());
m_out << "\n";
}
void display_info(func_decl_info* info) {
if (!info) {
return;
}
m_out << "BUILTIN " << get_family_name(info->get_family_id()) << " " << info->get_decl_kind() << " ";
if (info->is_associative()) {
m_out << ":assoc ";
}
if (info->is_commutative()) {
m_out << ":comm ";
}
if (info->is_injective()) {
m_out << ":inj ";
}
for (unsigned i = 0; i < info->get_num_parameters(); ++i) {
display_parameter(info->get_parameter(i));
}
}
void display_info(sort_info* info) {
if (!info) {
return;
}
m_out << "BUILTIN " << get_family_name(info->get_family_id()) << " " << info->get_decl_kind() << " ";
// TODO: remove this if... it doesn't make sense...
if (!info->is_infinite() && !info->is_very_big()) {
m_out << "Size " << info->get_num_elements().size() << " ";
}
for (unsigned i = 0; i < info->get_num_parameters(); ++i) {
display_parameter(info->get_parameter(i));
}
}
symbol get_family_name(family_id id) {
if (id == null_family_id) {
return symbol("null");
}
if (!m_initialized) {
svector<symbol> names;
svector<family_id> range;
m_manager.get_dom(names);
m_manager.get_range(range);
m_names.resize(range.size());
for (unsigned i = 0; i < range.size(); ++i) {
SASSERT(range[i] < static_cast<family_id>(range.size()));
m_names[range[i]] = names[i];
}
m_initialized = true;
}
SASSERT(id < static_cast<family_id>(m_names.size()));
return m_names[id];
}
bool has_special_char(char const* s) {
while (s && *s) {
if (*s == ' ') {
return true;
}
++s;
}
return false;
}
void display_symbol(symbol const& s) {
if (s.is_numerical()) {
m_out << s << " ";
}
else if (!(s.bare_str()[0])) {
m_out << "\"null\" ";
}
else if (!has_special_char(s.bare_str())) {
m_out << s << " ";
}
else {
char const* r = s.bare_str();
m_out << "\"";
while (*r) {
if (*r == ' ' || *r == '\n' ||
*r == '\t' || *r == '\r') {
m_out << "\\" << ((unsigned)(*r));
}
else {
m_out << *r;
}
++r;
}
m_out << "\" ";
}
}
public:
dag_printer(ast_manager& mgr, std::ostream & out, ast_mark& mark):
m_manager(mgr),
m_out(out),
m_mark(mark),
m_initialized(false),
m_basic_fid(mgr.get_basic_family_id()),
m_bv_fid(mgr.get_family_id("bv")),
m_arith_fid(mgr.get_family_id("arith")),
m_array_fid(mgr.get_family_id("array")),
m_arith(mgr),
m_bv(mgr),
m_enable_shortcut(true)
{
}
void operator()(sort * n) {
process_info(n->get_info());
m_out << "Ty ";
display_node_id(n);
display_symbol(n->get_name());
display_info(n->get_info());
m_out << "\n";
}
void pp_num(app* n, rational const& r) {
m_out << "Num ";
display_node_id(n);
m_out << r << " ";
display_node_id(m_manager.get_sort(n));
m_out << "\n";
}
void operator()(var * n) {
process_ast(n->get_sort());
m_out << "Var ";
display_node_id(n);
m_out << n->get_idx() << " ";
display_node_id(n->get_sort());
m_out << "\n";
}
void operator()(func_decl * n) {
process_info(n->get_info());
family_id fid = n->get_family_id();
if (m_arith_fid == fid &&
n->get_info()->get_decl_kind() == OP_NUM) {
return;
}
if (m_bv_fid == fid &&
n->get_info()->get_decl_kind() == OP_BV_NUM) {
return;
}
m_out << "Dec ";
display_node_id(n);
display_symbol(n->get_name());
unsigned dom_size = n->get_arity();
for (unsigned i = 0; i < dom_size; ++i) {
display_node_id(n->get_domain(i));
}
display_node_id(n->get_range());
display_info(n->get_info());
m_out << "\n";
}
void operator()(app * n) {
process_ast(n->get_decl());
family_id fid = n->get_family_id();
unsigned bv_size;
rational val;
if (m_arith.is_numeral(n, val)) {
pp_num(n, val);
}
else if (m_bv.is_numeral(n, val, bv_size)) {
pp_num(n, val);
}
else if (m_enable_shortcut &&
fid != null_family_id &&
(fid == m_basic_fid || fid == m_bv_fid || fid == m_array_fid || fid == m_arith_fid)) {
display_builtin(n);
}
else if (n->get_num_args() == 0 && fid == null_family_id) {
func_decl* d = n->get_decl();
m_out << "Const ";
display_node_id(n);
display_symbol(d->get_name());
display_node_id(d->get_range());
m_out << "\n";
}
else {
m_out << "Fun ";
display_node_id(n);
display_node_id(n->get_decl());
display_children(n->get_num_args(), n->get_args());
m_out << "\n";
}
}
void operator()(quantifier * n) {
m_out << "Qua ";
display_node_id(n);
m_out << (n->is_forall() ? "FORALL" : "EXISTS") << " ";
m_out << n->get_weight() << " ";
if (symbol::null != n->get_skid()) {
m_out << "\"" << n->get_skid() << "\" ";
}
else {
m_out << "\"null\" ";
}
if (symbol::null != n->get_qid()) {
m_out << "\"" << n->get_qid() << "\" ";
}
else {
m_out << "\"null\" ";
}
unsigned num_decls = n->get_num_decls();
m_out << num_decls << " ";
for (unsigned i = 0; i < num_decls; i++) {
m_out << n->get_decl_name(i) << " ";
display_node_id(n->get_decl_sort(i));
}
m_out << n->get_num_patterns() << " ";
display_children(n->get_num_patterns(), n->get_patterns());
display_node_id(n->get_expr());
m_out << "\n";
}
};
void ast_dag_pp(std::ostream & out, ast_manager& mgr, ast_mark& mark, ast * n) {
dag_printer p(mgr, out, mark);
for_each_ast(p, mark, n, true);
}
void ast_dag_pp(std::ostream & out, ast_manager& mgr, ast * n) {
ast_mark mark;
ast_dag_pp(out, mgr, mark, n);
}

31
src/ast/ast_dag_pp.h Normal file
View file

@ -0,0 +1,31 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
ast_dag_pp.h
Abstract:
AST low level pretty printer.
Author:
Leonardo de Moura (leonardo) 2006-10-19.
Revision History:
--*/
#ifndef _AST_DAG_PP_H_
#define _AST_DAG_PP_H_
#include<iostream>
class ast;
void ast_dag_pp(std::ostream & out, ast_manager& mgr, ast * n);
void ast_dag_pp(std::ostream & out, ast_manager& mgr, ast_mark& mark, ast * n);
#endif /* _AST_DAG_PP_H_ */

144
src/ast/ast_lt.cpp Normal file
View file

@ -0,0 +1,144 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ast_lt.cpp
Abstract:
Total order on ASTs that does not depend on the internal ids.
Author:
Leonardo de Moura (leonardo) 2011-04-08
Revision History:
--*/
#include"ast.h"
#define check_symbol(S1,S2) if (S1 != S2) return lt(S1,S2)
#define check_value(V1,V2) if (V1 != V2) return V1 < V2
#define check_bool(B1,B2) if (B1 != B2) return !B1 && B2
#define check_ptr(P1,P2) if (!P1 && P2) return true; if (P1 && !P2) return false
#define check_ast(T1,T2) if (T1 != T2) { n1 = T1; n2 = T2; goto start; }
#define check_parameter(p1, p2) { \
check_value(p1.get_kind(), p2.get_kind()); \
switch (p1.get_kind()) { \
case parameter::PARAM_INT: \
check_value(p1.get_int(), p2.get_int()); \
break; \
case parameter::PARAM_AST: \
check_ast(p1.get_ast(), p2.get_ast()); \
break; \
case parameter::PARAM_SYMBOL: \
check_symbol(p1.get_symbol(), p2.get_symbol()); \
break; \
case parameter::PARAM_RATIONAL: \
check_value(p1.get_rational(), p2.get_rational()); \
break; \
case parameter::PARAM_DOUBLE: \
check_value(p1.get_double(), p2.get_double()); \
break; \
case parameter::PARAM_EXTERNAL: \
check_value(p1.get_ext_id(), p2.get_ext_id()); \
break; \
default: \
UNREACHABLE(); \
break; \
} \
}
bool lt(ast * n1, ast * n2) {
unsigned num;
start:
if (n1 == n2)
return false;
check_value(n1->get_kind(), n2->get_kind());
switch(n1->get_kind()) {
case AST_SORT:
check_symbol(to_sort(n1)->get_name(), to_sort(n2)->get_name());
check_value(to_sort(n1)->get_num_parameters(), to_sort(n2)->get_num_parameters());
num = to_sort(n1)->get_num_parameters();
SASSERT(num > 0);
for (unsigned i = 0; i < num; i++) {
parameter p1 = to_sort(n1)->get_parameter(i);
parameter p2 = to_sort(n2)->get_parameter(i);
check_parameter(p1, p2);
}
UNREACHABLE();
return false;
case AST_FUNC_DECL:
check_symbol(to_func_decl(n1)->get_name(), to_func_decl(n2)->get_name());
check_value(to_func_decl(n1)->get_arity(), to_func_decl(n2)->get_arity());
check_value(to_func_decl(n1)->get_num_parameters(), to_func_decl(n2)->get_num_parameters());
num = to_func_decl(n1)->get_num_parameters();
for (unsigned i = 0; i < num; i++) {
parameter p1 = to_func_decl(n1)->get_parameter(i);
parameter p2 = to_func_decl(n2)->get_parameter(i);
check_parameter(p1, p2);
}
num = to_func_decl(n1)->get_arity();
for (unsigned i = 0; i < num; i++) {
ast * d1 = to_func_decl(n1)->get_domain(i);
ast * d2 = to_func_decl(n2)->get_domain(i);
check_ast(d1, d2);
}
n1 = to_func_decl(n1)->get_range();
n2 = to_func_decl(n2)->get_range();
goto start;
case AST_APP:
check_value(to_app(n1)->get_num_args(), to_app(n2)->get_num_args());
check_value(to_app(n1)->get_depth(), to_app(n2)->get_depth());
check_ast(to_app(n1)->get_decl(), to_app(n2)->get_decl());
num = to_app(n1)->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * arg1 = to_app(n1)->get_arg(i);
expr * arg2 = to_app(n2)->get_arg(i);
check_ast(arg1, arg2);
}
UNREACHABLE();
return false;
case AST_QUANTIFIER:
check_bool(to_quantifier(n1)->is_forall(), to_quantifier(n2)->is_forall());
check_value(to_quantifier(n1)->get_num_decls(), to_quantifier(n2)->get_num_decls());
check_value(to_quantifier(n1)->get_num_patterns(), to_quantifier(n2)->get_num_patterns());
check_value(to_quantifier(n1)->get_num_no_patterns(), to_quantifier(n2)->get_num_no_patterns());
check_value(to_quantifier(n1)->get_weight(), to_quantifier(n2)->get_weight());
num = to_quantifier(n1)->get_num_decls();
for (unsigned i = 0; i < num; i++) {
check_symbol(to_quantifier(n1)->get_decl_name(i), to_quantifier(n2)->get_decl_name(i));
check_ast(to_quantifier(n1)->get_decl_sort(i), to_quantifier(n2)->get_decl_sort(i));
}
num = to_quantifier(n1)->get_num_patterns();
for (unsigned i = 0; i < num; i++) {
check_ast(to_quantifier(n1)->get_pattern(i), to_quantifier(n2)->get_pattern(i));
}
num = to_quantifier(n1)->get_num_no_patterns();
for (unsigned i = 0; i < num; i++) {
check_ast(to_quantifier(n1)->get_no_pattern(i), to_quantifier(n2)->get_no_pattern(i));
}
n1 = to_quantifier(n1)->get_expr();
n2 = to_quantifier(n2)->get_expr();
goto start;
case AST_VAR:
check_value(to_var(n1)->get_idx(), to_var(n2)->get_idx());
n1 = to_var(n1)->get_sort();
n2 = to_var(n2)->get_sort();
goto start;
default:
UNREACHABLE();
return false;
}
}
bool lex_lt(unsigned num, ast * const * n1, ast * const * n2) {
for (unsigned i = 0; i < num; i ++) {
if (n1[i] == n2[i])
continue;
return lt(n1[i], n2[i]);
}
return false;
}

35
src/ast/ast_lt.h Normal file
View file

@ -0,0 +1,35 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ast_lt.h
Abstract:
Total order on ASTs that does not depend on the internal ids.
Author:
Leonardo de Moura (leonardo) 2011-04-08
Revision History:
--*/
#ifndef _AST_LT_H_
#define _AST_LT_H_
class ast;
bool lt(ast * n1, ast * n2);
struct ast_to_lt {
bool operator()(ast * n1, ast * n2) const { return lt(n1, n2); }
};
bool lex_lt(unsigned num, ast * const * n1, ast * const * n2);
inline bool lex_lt(unsigned num, expr * const * n1, expr * const * n2) {
return lex_lt(num, reinterpret_cast<ast*const*>(n1), reinterpret_cast<ast*const*>(n2));
}
#endif

1224
src/ast/ast_smt_pp.cpp Normal file

File diff suppressed because it is too large Load diff

103
src/ast/ast_smt_pp.h Normal file
View file

@ -0,0 +1,103 @@
/*++
Copyright (c) 2008 Microsoft Corporation
Module Name:
ast_smt_pp.h
Abstract:
Pretty printer of AST formulas as SMT benchmarks.
Author:
Nikolaj Bjorner 2008-04-09.
Revision History:
--*/
#ifndef _AST_SMT_PP_H_
#define _AST_SMT_PP_H_
#include"ast.h"
#include<string>
#include"map.h"
class smt_renaming {
typedef map<symbol, symbol, symbol_hash_proc, symbol_eq_proc> symbol2symbol;
symbol2symbol m_translate;
symbol2symbol m_rev_translate;
symbol fix_symbol(symbol s, int k);
bool is_legal(char c);
bool is_special(char const* s);
bool is_numerical(char const* s);
bool all_is_legal(char const* s);
public:
smt_renaming();
symbol get_symbol(symbol s0);
symbol operator()(symbol const & s) { return get_symbol(s); }
};
class ast_smt_pp {
public:
class is_declared {
public:
virtual bool operator()(func_decl* d) const { return false; }
virtual bool operator()(sort* s) const { return false; }
};
private:
ast_manager& m_manager;
expr_ref_vector m_assumptions;
expr_ref_vector m_assumptions_star;
symbol m_benchmark_name;
symbol m_source_info;
symbol m_status;
symbol m_category;
symbol m_logic;
std::string m_attributes;
family_id m_dt_fid;
is_declared m_is_declared_default;
is_declared* m_is_declared;
bool m_simplify_implies;
public:
ast_smt_pp(ast_manager& m);
void set_benchmark_name(const char* bn) { if (bn) m_benchmark_name = bn; }
void set_source_info(const char* si) { if (si) m_source_info = si; }
void set_status(const char* s) { if (s) m_status = s; }
void set_category(const char* c) { if (c) m_category = c; }
void set_logic(const char* l) { if (l) m_logic = l; }
void add_attributes(const char* s) { if (s) m_attributes += s; }
void add_assumption(expr* n) { m_assumptions.push_back(n); }
void add_assumption_star(expr* n) { m_assumptions_star.push_back(n); }
void set_simplify_implies(bool f) { m_simplify_implies = f; }
void set_is_declared(is_declared* id) { m_is_declared = id; }
void display(std::ostream& strm, expr* n);
void display_smt2(std::ostream& strm, expr* n);
void display_expr(std::ostream& strm, expr* n);
void display_expr_smt2(std::ostream& strm, expr* n, unsigned indent = 0, unsigned num_var_names = 0, char const* const* var_names = 0);
};
struct mk_smt_pp {
expr * m_expr;
ast_manager& m_manager;
unsigned m_indent;
unsigned m_num_var_names;
char const* const* m_var_names;
mk_smt_pp(expr* e, ast_manager & m, unsigned indent = 0, unsigned num_var_names = 0, char const* const* var_names = 0) :
m_expr(e), m_manager(m), m_indent(indent), m_num_var_names(num_var_names), m_var_names(var_names) {}
};
inline std::ostream& operator<<(std::ostream& out, const mk_smt_pp & p) {
ast_smt_pp pp(p.m_manager);
pp.display_expr_smt2(out, p.m_expr, p.m_indent, p.m_num_var_names, p.m_var_names);
return out;
}
#endif

331
src/ast/ast_translation.cpp Normal file
View file

@ -0,0 +1,331 @@
/*++
Copyright (c) 2008 Microsoft Corporation
Module Name:
ast_translation.cpp
Abstract:
AST translation functions
Author:
Christoph Wintersteiger (t-cwinte) 2008-11-20
Revision History:
--*/
#include "arith_decl_plugin.h"
#include "bv_decl_plugin.h"
#include "datatype_decl_plugin.h"
#include "array_decl_plugin.h"
#include "format.h"
#include "ast_translation.h"
#include "ast_ll_pp.h"
ast_translation::~ast_translation() {
reset_cache();
}
void ast_translation::cleanup() {
reset_cache();
m_cache.finalize();
m_result_stack.finalize();
m_frame_stack.finalize();
m_extra_children_stack.finalize();
}
void ast_translation::reset_cache() {
obj_map<ast, ast*>::iterator it = m_cache.begin();
obj_map<ast, ast*>::iterator end = m_cache.end();
for (; it != end; ++it) {
m_from_manager.dec_ref(it->m_key);
m_to_manager.dec_ref(it->m_value);
}
m_cache.reset();
}
void ast_translation::cache(ast * s, ast * t) {
SASSERT(!m_cache.contains(s));
if (s->get_ref_count() > 1) {
m_cache.insert(s, t);
m_from_manager.inc_ref(s);
m_to_manager.inc_ref(t);
}
}
void ast_translation::collect_decl_extra_children(decl * d) {
unsigned num_params = d->get_num_parameters();
for (unsigned i = 0; i < num_params; i++) {
parameter const & p = d->get_parameter(i);
if (p.is_ast())
m_extra_children_stack.push_back(p.get_ast());
}
}
void ast_translation::push_frame(ast * n) {
m_frame_stack.push_back(frame(n, 0, m_extra_children_stack.size(), m_result_stack.size()));
switch (n->get_kind()) {
case AST_SORT:
case AST_FUNC_DECL:
collect_decl_extra_children(to_decl(n));
break;
default:
break;
}
}
bool ast_translation::visit(ast * n) {
ast * r;
if (n->get_ref_count() > 1 && m_cache.find(n, r)) {
m_result_stack.push_back(r);
return true;
}
push_frame(n);
return false;
}
void ast_translation::copy_params(decl * d, unsigned rpos, buffer<parameter> & ps) {
unsigned num = d->get_num_parameters();
unsigned j = rpos;
for (unsigned i = 0; i < num; i++) {
parameter const & p = d->get_parameter(i);
if (p.is_ast()) {
ps.push_back(parameter(m_result_stack[j]));
j++;
}
else if (p.is_external()) {
SASSERT(d->get_family_id() != null_family_id);
decl_plugin & from_plugin = *(m_from_manager.get_plugin(d->get_family_id()));
decl_plugin & to_plugin = *(m_to_manager.get_plugin(d->get_family_id()));
ps.push_back(from_plugin.translate(p, to_plugin));
}
else {
ps.push_back(p);
}
}
}
void ast_translation::mk_sort(sort * s, frame & fr) {
sort_info * si = s->get_info();
sort * new_s;
if (si == 0) {
new_s = m_to_manager.mk_sort(s->get_name());
SASSERT(m_result_stack.size() == fr.m_rpos);
}
else {
buffer<parameter> ps;
copy_params(s, fr.m_rpos, ps);
new_s = m_to_manager.mk_sort(s->get_name(), sort_info(si->get_family_id(),
si->get_decl_kind(),
si->get_num_elements(),
si->get_num_parameters(),
ps.c_ptr(),
s->private_parameters()));
}
m_result_stack.shrink(fr.m_rpos);
m_result_stack.push_back(new_s);
m_extra_children_stack.shrink(fr.m_cpos);
cache(s, new_s);
m_frame_stack.pop_back();
}
void ast_translation::mk_func_decl(func_decl * f, frame & fr) {
func_decl_info * fi = f->get_info();
SASSERT(fr.m_cpos <= m_extra_children_stack.size());
unsigned num_extra = m_extra_children_stack.size() - fr.m_cpos;
sort ** new_domain = reinterpret_cast<sort**>(m_result_stack.c_ptr() + fr.m_rpos + num_extra);
sort * new_range = static_cast<sort*>(m_result_stack.back());
func_decl * new_f;
if (fi == 0) {
new_f = m_to_manager.mk_func_decl(f->get_name(),
f->get_arity(),
new_domain,
new_range);
}
else {
buffer<parameter> ps;
copy_params(f, fr.m_rpos, ps);
func_decl_info new_fi(fi->get_family_id(),
fi->get_decl_kind(),
fi->get_num_parameters(),
ps.c_ptr());
new_fi.set_left_associative(fi->is_left_associative());
new_fi.set_right_associative(fi->is_right_associative());
new_fi.set_flat_associative(fi->is_flat_associative());
new_fi.set_commutative(fi->is_commutative());
new_fi.set_chainable(fi->is_chainable());
new_fi.set_pairwise(fi->is_pairwise());
new_fi.set_injective(fi->is_injective());
new_fi.set_skolem(fi->is_skolem());
new_fi.set_idempotent(fi->is_idempotent());
new_f = m_to_manager.mk_func_decl(f->get_name(),
f->get_arity(),
new_domain,
new_range,
new_fi);
}
TRACE("ast_translation",
tout << f->get_name() << " "; if (fi) tout << *fi; tout << "\n";
tout << "---->\n";
tout << new_f->get_name() << " "; if (new_f->get_info()) tout << *(new_f->get_info()); tout << "\n";);
m_result_stack.shrink(fr.m_rpos);
m_result_stack.push_back(new_f);
m_extra_children_stack.shrink(fr.m_cpos);
cache(f, new_f);
m_frame_stack.pop_back();
}
ast * ast_translation::process(ast const * _n) {
SASSERT(m_result_stack.empty());
SASSERT(m_frame_stack.empty());
SASSERT(m_extra_children_stack.empty());
if (!visit(const_cast<ast*>(_n))) {
while (!m_frame_stack.empty()) {
loop:
frame & fr = m_frame_stack.back();
ast * n = fr.m_n;
ast * r;
TRACE("ast_translation", tout << mk_ll_pp(n, m_from_manager, false) << "\n";);
if (fr.m_idx == 0 && n->get_ref_count() > 1 && m_cache.find(n, r)) {
SASSERT(m_result_stack.size() == fr.m_rpos);
m_result_stack.push_back(r);
m_extra_children_stack.shrink(fr.m_cpos);
m_frame_stack.pop_back();
TRACE("ast_translation", tout << "hit\n";);
continue;
}
switch (n->get_kind()) {
case AST_VAR: {
if (fr.m_idx == 0) {
fr.m_idx = 1;
if (!visit(to_var(n)->get_sort()))
goto loop;
}
sort * new_s = to_sort(m_result_stack.back());
var * new_var = m_to_manager.mk_var(to_var(n)->get_idx(), new_s);
m_result_stack.pop_back();
m_result_stack.push_back(new_var);
cache(n, new_var);
m_frame_stack.pop_back();
break;
}
case AST_APP: {
if (fr.m_idx == 0) {
fr.m_idx = 1;
if (!visit(to_app(n)->get_decl()))
goto loop;
}
unsigned num = to_app(n)->get_num_args();
while (fr.m_idx <= num) {
expr * arg = to_app(n)->get_arg(fr.m_idx - 1);
fr.m_idx++;
if (!visit(arg))
goto loop;
}
func_decl * new_f = to_func_decl(m_result_stack[fr.m_rpos]);
expr ** new_args = reinterpret_cast<expr **>(m_result_stack.c_ptr() + fr.m_rpos + 1);
expr * new_app = m_to_manager.mk_app(new_f, num, new_args);
m_result_stack.shrink(fr.m_rpos);
m_result_stack.push_back(new_app);
cache(n, new_app);
m_frame_stack.pop_back();
break;
}
case AST_QUANTIFIER: {
unsigned num_decls = to_quantifier(n)->get_num_decls();
unsigned num = num_decls + to_quantifier(n)->get_num_children();
while (fr.m_idx < num) {
ast * child;
if (fr.m_idx < num_decls)
child = to_quantifier(n)->get_decl_sort(fr.m_idx);
else
child = to_quantifier(n)->get_child(fr.m_idx - num_decls);
fr.m_idx++;
if (!visit(child))
goto loop;
}
symbol const * dnames = to_quantifier(n)->get_decl_names();
sort ** dsorts = reinterpret_cast<sort**>(m_result_stack.c_ptr() + fr.m_rpos);
expr * body = static_cast<expr*>(m_result_stack[fr.m_rpos + num_decls]);
unsigned num_pats = to_quantifier(n)->get_num_patterns();
expr ** pats = reinterpret_cast<expr**>(m_result_stack.c_ptr() + fr.m_rpos + num_decls + 1);
unsigned num_no_pats = to_quantifier(n)->get_num_no_patterns();
expr ** no_pats = pats + num_pats;
quantifier * new_q = m_to_manager.mk_quantifier(to_quantifier(n)->is_forall(),
num_decls,
dsorts,
dnames,
body,
to_quantifier(n)->get_weight(),
to_quantifier(n)->get_qid(),
to_quantifier(n)->get_skid(),
num_pats, pats,
num_no_pats, no_pats);
m_result_stack.shrink(fr.m_rpos);
m_result_stack.push_back(new_q);
cache(n, new_q);
m_frame_stack.pop_back();
break;
}
case AST_SORT: {
SASSERT(fr.m_cpos <= m_extra_children_stack.size());
unsigned num = m_extra_children_stack.size() - fr.m_cpos;
while (fr.m_idx < num) {
ast * c = m_extra_children_stack[fr.m_cpos + fr.m_idx];
fr.m_idx++;
if (!visit(c))
goto loop;
}
mk_sort(to_sort(n), fr);
break;
}
case AST_FUNC_DECL: {
SASSERT(fr.m_cpos <= m_extra_children_stack.size());
unsigned num_extra = m_extra_children_stack.size() - fr.m_cpos;
unsigned arity = to_func_decl(n)->get_arity();
unsigned num = num_extra + arity + 1;
while (fr.m_idx < num) {
ast * c;
if (fr.m_idx < num_extra)
c = m_extra_children_stack[fr.m_cpos + fr.m_idx];
else if (fr.m_idx < num_extra + arity)
c = to_func_decl(n)->get_domain(fr.m_idx - num_extra);
else
c = to_func_decl(n)->get_range();
fr.m_idx++;
if (!visit(c))
goto loop;
}
mk_func_decl(to_func_decl(n), fr);
break;
}
default:
UNREACHABLE();
break;
}
}
}
SASSERT(m_result_stack.size() == 1);
ast * r = m_result_stack.back();
m_result_stack.reset();
return r;
}
expr_dependency * expr_dependency_translation::operator()(expr_dependency * d) {
if (d == 0)
return d;
m_buffer.reset();
m_translation.from().linearize(d, m_buffer);
unsigned sz = m_buffer.size();
SASSERT(sz >= 1);
for (unsigned i = 0; i < sz; i++) {
m_buffer[i] = m_translation(m_buffer[i]);
}
return m_translation.to().mk_join(sz, m_buffer.c_ptr());
}

97
src/ast/ast_translation.h Normal file
View file

@ -0,0 +1,97 @@
/*++
Copyright (c) 2008 Microsoft Corporation
Module Name:
ast_translation.h
Abstract:
AST translation functions
Author:
Christoph Wintersteiger (t-cwinte) 2008-11-20
Revision History:
2011-05-26: New local translation class.
--*/
#ifndef _AST_TRANSLATION_H_
#define _AST_TRANSLATION_H_
#include"ast.h"
class ast_translation {
struct frame {
ast * m_n;
unsigned m_idx;
unsigned m_cpos;
unsigned m_rpos;
frame(ast * n, unsigned idx, unsigned cpos, unsigned rpos):m_n(n), m_idx(idx), m_cpos(cpos), m_rpos(rpos) {}
};
ast_manager & m_from_manager;
ast_manager & m_to_manager;
svector<frame> m_frame_stack;
ptr_vector<ast> m_extra_children_stack; // for sort and func_decl, since they have nested AST in their parameters
ptr_vector<ast> m_result_stack;
obj_map<ast, ast*> m_cache;
void cache(ast * s, ast * t);
void collect_decl_extra_children(decl * d);
void push_frame(ast * n);
bool visit(ast * n);
void copy_params(decl * d, unsigned rpos, buffer<parameter> & ps);
void mk_sort(sort * s, frame & fr);
void mk_func_decl(func_decl * f, frame & fr);
ast * process(ast const * n);
public:
ast_translation(ast_manager & from, ast_manager & to, bool copy_plugins = true) : m_from_manager(from), m_to_manager(to) {
if (copy_plugins)
m_to_manager.copy_families_plugins(m_from_manager);
}
~ast_translation();
template<typename T>
T * operator()(T const * n) {
SASSERT(from().contains(const_cast<T*>(n)));
ast * r = process(n);
SASSERT(to().contains(const_cast<ast*>(r)));
return static_cast<T*>(r);
}
ast_manager & from() const { return m_from_manager; }
ast_manager & to() const { return m_to_manager; }
void reset_cache();
void cleanup();
};
// Translation with non-persistent cache.
inline ast * translate(ast const * a, ast_manager & from, ast_manager & to) {
return ast_translation(from, to)(a);
}
inline expr * translate(expr const * e, ast_manager & from, ast_manager & to) {
return ast_translation(from, to)(e);
}
class expr_dependency_translation {
ast_translation & m_translation;
ptr_vector<expr> m_buffer;
public:
expr_dependency_translation(ast_translation & t):m_translation(t) {}
expr_dependency * operator()(expr_dependency * d);
};
inline expr_dependency * translate(expr_dependency * d, ast_manager & from, ast_manager & to) {
ast_translation t(from, to);
expr_dependency_translation td(t);
return td(d);
}
#endif

102
src/ast/decl_collector.cpp Normal file
View file

@ -0,0 +1,102 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
smt_decl_collector.cpp
Abstract:
Collect uninterpreted func_delcs and sorts.
This class was originally in ast_smt_pp.h
Author:
Leonardo (leonardo) 2011-10-04
Revision History:
--*/
#include"decl_collector.h"
void decl_collector::visit_sort(sort * n) {
family_id fid = n->get_family_id();
if (m().is_uninterp(n))
m_sorts.push_back(n);
if (fid == m_dt_fid)
m_sorts.push_back(n);
}
bool decl_collector::is_bool(sort * s) {
return m().is_bool(s);
}
void decl_collector::visit_func(func_decl * n) {
family_id fid = n->get_family_id();
if (fid == null_family_id) {
if (m_sep_preds && is_bool(n->get_range()))
m_preds.push_back(n);
else
m_decls.push_back(n);
}
}
decl_collector::decl_collector(ast_manager & m, bool preds):
m_manager(m),
m_sep_preds(preds) {
m_basic_fid = m_manager.get_basic_family_id();
m_dt_fid = m_manager.get_family_id("datatype");
}
void decl_collector::visit(ast* n) {
ptr_vector<ast> todo;
todo.push_back(n);
while (!todo.empty()) {
n = todo.back();
todo.pop_back();
if (!m_visited.is_marked(n)) {
m_visited.mark(n, true);
switch(n->get_kind()) {
case AST_APP: {
app * a = to_app(n);
for (unsigned i = 0; i < a->get_num_args(); ++i) {
todo.push_back(a->get_arg(i));
}
todo.push_back(a->get_decl());
break;
}
case AST_QUANTIFIER: {
quantifier * q = to_quantifier(n);
unsigned num_decls = q->get_num_decls();
for (unsigned i = 0; i < num_decls; ++i) {
todo.push_back(q->get_decl_sort(i));
}
todo.push_back(q->get_expr());
for (unsigned i = 0; i < q->get_num_patterns(); ++i) {
todo.push_back(q->get_pattern(i));
}
break;
}
case AST_SORT:
visit_sort(to_sort(n));
break;
case AST_FUNC_DECL: {
func_decl * d = to_func_decl(n);
for (unsigned i = 0; i < d->get_arity(); ++i) {
todo.push_back(d->get_domain(i));
}
todo.push_back(d->get_range());
visit_func(d);
break;
}
case AST_VAR:
break;
default:
UNREACHABLE();
}
}
}
}

55
src/ast/decl_collector.h Normal file
View file

@ -0,0 +1,55 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
decl_collector.h
Abstract:
Collect uninterpreted func_delcs and sorts.
This class was originally in ast_smt_pp.h
Author:
Leonardo (leonardo) 2011-10-04
Revision History:
--*/
#ifndef _SMT_DECL_COLLECTOR_H_
#define _SMT_DECL_COLLECTOR_H_
#include"ast.h"
class decl_collector {
ast_manager & m_manager;
bool m_sep_preds;
ptr_vector<sort> m_sorts;
ptr_vector<func_decl> m_decls;
ptr_vector<func_decl> m_preds;
ast_mark m_visited;
family_id m_basic_fid;
family_id m_dt_fid;
void visit_sort(sort* n);
bool is_bool(sort* s);
void visit_func(func_decl* n);
public:
// if preds == true, then predicates are stored in a separate collection.
decl_collector(ast_manager & m, bool preds=true);
ast_manager & m() { return m_manager; }
void visit(ast * n);
unsigned get_num_sorts() const { return m_sorts.size(); }
unsigned get_num_decls() const { return m_decls.size(); }
unsigned get_num_preds() const { return m_preds.size(); }
sort * const * get_sorts() const { return m_sorts.c_ptr(); }
func_decl * const * get_func_decls() const { return m_decls.c_ptr(); }
func_decl * const * get_pred_decls() const { return m_preds.c_ptr(); }
};
#endif

36
src/ast/expr_delta_pair.h Normal file
View file

@ -0,0 +1,36 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
expr_delta_pair.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-01-14.
Revision History:
--*/
#ifndef _EXPR_DELTA_PAIR_H_
#define _EXPR_DELTA_PAIR_H_
/**
\brief Auxiliary structure used to cache the intermediate results of the variable substitution procedure.
*/
struct expr_delta_pair {
expr * m_node;
unsigned m_delta;
expr_delta_pair():m_node(0), m_delta(0) {}
expr_delta_pair(expr * n, unsigned d):m_node(n), m_delta(d) {}
unsigned hash() const { return hash_u_u(m_node->hash(), m_delta); }
bool operator==(const expr_delta_pair & e) const { return m_node == e.m_node && m_delta == e.m_delta; }
};
#endif /* _EXPR_DELTA_PAIR_H_ */

View file

@ -0,0 +1,157 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
expr_substitution.cpp
Abstract:
expr -> expr substitution
Author:
Leonardo (leonardo) 2011-04-29
Notes:
--*/
#include"expr_substitution.h"
#include"ref_util.h"
typedef obj_map<expr, proof*> expr2proof;
typedef obj_map<expr, expr_dependency*> expr2expr_dependency;
void expr_substitution::init() {
if (proofs_enabled())
m_subst_pr = alloc(expr2proof);
if (unsat_core_enabled())
m_subst_dep = alloc(expr2expr_dependency);
}
expr_substitution::expr_substitution(ast_manager & m):
m_manager(m),
m_cores_enabled(false),
m_proofs_enabled(m.proofs_enabled()) {
init();
}
expr_substitution::expr_substitution(ast_manager & m, bool core_enabled):
m_manager(m),
m_cores_enabled(core_enabled),
m_proofs_enabled(m.proofs_enabled()) {
init();
}
expr_substitution::expr_substitution(ast_manager & m, bool core_enabled, bool proofs_enabled):
m_manager(m),
m_cores_enabled(core_enabled),
m_proofs_enabled(proofs_enabled) {
SASSERT(!proofs_enabled || m.proofs_enabled());
init();
}
expr_substitution::~expr_substitution() {
reset();
}
void expr_substitution::insert(expr * c, expr * def, proof * def_pr, expr_dependency * def_dep) {
obj_map<expr, expr*>::obj_map_entry * entry = m_subst.insert_if_not_there2(c, 0);
if (entry->get_data().m_value == 0) {
// new entry
m_manager.inc_ref(c);
m_manager.inc_ref(def);
entry->get_data().m_value = def;
if (proofs_enabled()) {
SASSERT(!m_subst_pr->contains(c));
m_subst_pr->insert(c, def_pr);
m_manager.inc_ref(def_pr);
}
if (unsat_core_enabled()) {
SASSERT(!m_subst_dep->contains(c));
m_subst_dep->insert(c, def_dep);
m_manager.inc_ref(def_dep);
}
}
else {
// replacing entry
m_manager.inc_ref(def);
m_manager.dec_ref(entry->get_data().m_value);
entry->get_data().m_value = def;
if (proofs_enabled()) {
obj_map<expr, proof*>::obj_map_entry * entry_pr = m_subst_pr->find_core(c);
SASSERT(entry_pr != 0);
m_manager.inc_ref(def_pr);
m_manager.dec_ref(entry_pr->get_data().m_value);
entry_pr->get_data().m_value = def_pr;
}
if (unsat_core_enabled()) {
obj_map<expr, expr_dependency*>::obj_map_entry * entry_dep = m_subst_dep->find_core(c);
SASSERT(entry_dep != 0);
m_manager.inc_ref(def_dep);
m_manager.dec_ref(entry_dep->get_data().m_value);
entry_dep->get_data().m_value = def_dep;
}
}
}
void expr_substitution::erase(expr * c) {
if (proofs_enabled()) {
proof * pr = 0;
if (m_subst_pr->find(c, pr)) {
m_manager.dec_ref(pr);
m_subst_pr->erase(c);
}
}
if (unsat_core_enabled()) {
expr_dependency * dep = 0;
if (m_subst_dep->find(c, dep)) {
m_manager.dec_ref(dep);
m_subst_dep->erase(c);
}
}
expr * def = 0;
if (m_subst.find(c, def)) {
m_manager.dec_ref(c);
m_manager.dec_ref(def);
m_subst.erase(c);
}
}
bool expr_substitution::find(expr * c, expr * & def, proof * & def_pr) {
if (m_subst.find(c, def)) {
if (proofs_enabled())
m_subst_pr->find(c, def_pr);
return true;
}
return false;
}
bool expr_substitution::find(expr * c, expr * & def, proof * & def_pr, expr_dependency * & def_dep) {
if (m_subst.find(c, def)) {
if (proofs_enabled())
m_subst_pr->find(c, def_pr);
if (unsat_core_enabled())
m_subst_dep->find(c, def_dep);
return true;
}
return false;
}
void expr_substitution::reset() {
dec_ref_map_key_values(m_manager, m_subst);
if (proofs_enabled())
dec_ref_map_values(m_manager, *m_subst_pr);
if (unsat_core_enabled())
dec_ref_map_values(m_manager, *m_subst_dep);
}
void expr_substitution::cleanup() {
reset();
m_subst.finalize();
if (proofs_enabled())
m_subst_pr->finalize();
if (unsat_core_enabled())
m_subst_dep->finalize();
}

View file

@ -0,0 +1,54 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
expr_substitution.h
Abstract:
expr -> expr substitution
Author:
Leonardo (leonardo) 2011-04-29
Notes:
--*/
#ifndef _EXPR_SUBSTITUTION_H_
#define _EXPR_SUBSTITUTION_H_
#include"ast.h"
class expr_substitution {
ast_manager & m_manager;
obj_map<expr, expr*> m_subst;
scoped_ptr<obj_map<expr, proof*> > m_subst_pr;
scoped_ptr<obj_map<expr, expr_dependency*> > m_subst_dep;
unsigned m_cores_enabled:1;
unsigned m_proofs_enabled:1;
void init();
public:
expr_substitution(ast_manager & m);
expr_substitution(ast_manager & m, bool cores_enabled);
expr_substitution(ast_manager & m, bool cores_enabled, bool proofs_enabled);
~expr_substitution();
ast_manager & m() const { return m_manager; }
bool proofs_enabled() const { return m_proofs_enabled; }
bool unsat_core_enabled() const { return m_cores_enabled; }
bool empty() const { return m_subst.empty(); }
void insert(expr * s, expr * def, proof * def_pr = 0, expr_dependency * def_dep = 0);
void erase(expr * s);
bool find(expr * s, expr * & def, proof * & def_pr);
bool find(expr * s, expr * & def, proof * & def_pr, expr_dependency * & def_dep);
void reset();
void cleanup();
};
#endif

113
src/ast/used_vars.cpp Normal file
View file

@ -0,0 +1,113 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
used_vars.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-01-14.
Revision History:
--*/
#include"used_vars.h"
void used_vars::process(expr * n, unsigned delta) {
unsigned j, idx;
m_cache.reset();
m_todo.reset();
m_todo.push_back(expr_delta_pair(n, delta));
while (!m_todo.empty()) {
expr_delta_pair const & p = m_todo.back();
n = p.m_node;
if (n->get_ref_count() > 1 && m_cache.contains(p)) {
m_todo.pop_back();
continue;
}
if (n->get_ref_count() > 1) {
// cache only shared and non-constant nodes
m_cache.insert(p);
}
delta = p.m_delta;
m_todo.pop_back();
switch (n->get_kind()) {
case AST_APP:
j = to_app(n)->get_num_args();
while (j > 0) {
--j;
expr * arg = to_app(n)->get_arg(j);
m_todo.push_back(expr_delta_pair(arg, delta));
}
break;
case AST_VAR:
idx = to_var(n)->get_idx();
if (idx >= delta) {
idx = idx - delta;
if (idx >= m_found_vars.size())
m_found_vars.resize(idx + 1, 0);
m_found_vars[idx] = to_var(n)->get_sort();
}
break;
case AST_QUANTIFIER:
// recurse so that memoization is correct with respect to 'delta'.
delta += to_quantifier(n)->get_num_decls();
j = to_quantifier(n)->get_num_patterns();
while (j > 0) {
--j;
m_todo.push_back(expr_delta_pair(to_quantifier(n)->get_pattern(j), delta));
}
j = to_quantifier(n)->get_num_no_patterns();
while (j > 0) {
--j;
m_todo.push_back(expr_delta_pair(to_quantifier(n)->get_no_pattern(j), delta));
}
m_todo.push_back(expr_delta_pair(to_quantifier(n)->get_expr(), delta));
break;
default:
break;
}
}
}
bool used_vars::uses_all_vars(unsigned num_decls) const {
if (num_decls > m_found_vars.size())
return false;
for (unsigned i = 0; i < num_decls; i++) {
if (!m_found_vars[i])
return false;
}
return true;
}
bool used_vars::uses_a_var(unsigned num_decls) const {
num_decls = std::min(num_decls, m_found_vars.size());
for (unsigned i = 0; i < num_decls; i++) {
if (m_found_vars[i])
return true;
}
return false;
}
unsigned used_vars::get_num_vars() const {
unsigned r = 0;
unsigned num = m_found_vars.size();
for (unsigned i = 0; i < num; i++) {
if (m_found_vars[i])
return r++;
}
return r;
}

59
src/ast/used_vars.h Normal file
View file

@ -0,0 +1,59 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
used_vars.h
Abstract:
Functor used to collect the set of used variables.
Author:
Leonardo de Moura (leonardo) 2008-01-14.
Revision History:
--*/
#ifndef _USED_VARS_H_
#define _USED_VARS_H_
#include"ast.h"
#include"expr_delta_pair.h"
class used_vars {
ptr_vector<sort> m_found_vars;
typedef hashtable<expr_delta_pair, obj_hash<expr_delta_pair>, default_eq<expr_delta_pair> > cache;
cache m_cache;
svector<expr_delta_pair> m_todo;
void process(expr * n, unsigned delta);
public:
void operator()(expr * n) {
m_found_vars.reset();
process(n, 0);
}
void reset() {
m_found_vars.reset();
}
void process(expr * n) {
process(n, 0);
}
unsigned get_max_found_var_idx_plus_1() const { return m_found_vars.size(); }
sort * get(unsigned var_idx) const { return m_found_vars[var_idx]; }
sort * contains(unsigned var_idx) const { return var_idx < m_found_vars.size() ? m_found_vars[var_idx] : 0; }
bool uses_all_vars(unsigned num_decls) const;
bool uses_a_var(unsigned num_decls) const;
unsigned get_num_vars() const;
};
#endif /* _USED_VARS_H_ */