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:
parent
9a84cba6c9
commit
ded42feeb6
62 changed files with 4 additions and 115 deletions
224
src/ast/act_cache.cpp
Normal file
224
src/ast/act_cache.cpp
Normal 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
56
src/ast/act_cache.h
Normal 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
353
src/ast/ast_dag_pp.cpp
Normal 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
31
src/ast/ast_dag_pp.h
Normal 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
144
src/ast/ast_lt.cpp
Normal 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
35
src/ast/ast_lt.h
Normal 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
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
103
src/ast/ast_smt_pp.h
Normal 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
331
src/ast/ast_translation.cpp
Normal 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
97
src/ast/ast_translation.h
Normal 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
102
src/ast/decl_collector.cpp
Normal 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
55
src/ast/decl_collector.h
Normal 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
36
src/ast/expr_delta_pair.h
Normal 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_ */
|
||||
|
157
src/ast/expr_substitution.cpp
Normal file
157
src/ast/expr_substitution.cpp
Normal 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();
|
||||
}
|
54
src/ast/expr_substitution.h
Normal file
54
src/ast/expr_substitution.h
Normal 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
113
src/ast/used_vars.cpp
Normal 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
59
src/ast/used_vars.h
Normal 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_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue