mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
merge with master branch
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
651587ce01
1602 changed files with 40496 additions and 27837 deletions
|
@ -23,6 +23,7 @@ z3_add_component(ast
|
|||
expr_map.cpp
|
||||
expr_stat.cpp
|
||||
expr_substitution.cpp
|
||||
factor_equivs.cpp
|
||||
for_each_ast.cpp
|
||||
for_each_expr.cpp
|
||||
format.cpp
|
||||
|
|
|
@ -17,7 +17,7 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"act_cache.h"
|
||||
#include "ast/act_cache.h"
|
||||
|
||||
#define MIN_MAX_UNUSED 1024
|
||||
#define INITIAL_CAPACITY 128
|
||||
|
|
|
@ -20,9 +20,9 @@ Notes:
|
|||
#ifndef ACT_CACHE_H_
|
||||
#define ACT_CACHE_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"chashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "util/chashtable.h"
|
||||
|
||||
class act_cache {
|
||||
ast_manager & m_manager;
|
||||
|
|
|
@ -16,11 +16,11 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"warning.h"
|
||||
#include"algebraic_numbers.h"
|
||||
#include"id_gen.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "util/warning.h"
|
||||
#include "math/polynomial/algebraic_numbers.h"
|
||||
#include "util/id_gen.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
struct arith_decl_plugin::algebraic_numbers_wrapper {
|
||||
unsynch_mpq_manager m_qmanager;
|
||||
|
@ -81,8 +81,9 @@ app * arith_decl_plugin::mk_numeral(algebraic_numbers::anum const & val, bool is
|
|||
return mk_numeral(rval, is_int);
|
||||
}
|
||||
else {
|
||||
if (is_int)
|
||||
if (is_int) {
|
||||
m_manager->raise_exception("invalid irrational value passed as an integer");
|
||||
}
|
||||
unsigned idx = aw().mk_id(val);
|
||||
parameter p(idx, true);
|
||||
SASSERT(p.is_external());
|
||||
|
@ -214,18 +215,8 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
m_e = m->mk_const(e_decl);
|
||||
m->inc_ref(m_e);
|
||||
|
||||
func_decl * z_pw_z_int = m->mk_const_decl(symbol("0^0-int"), i, func_decl_info(id, OP_0_PW_0_INT));
|
||||
m_0_pw_0_int = m->mk_const(z_pw_z_int);
|
||||
m->inc_ref(m_0_pw_0_int);
|
||||
|
||||
func_decl * z_pw_z_real = m->mk_const_decl(symbol("0^0-real"), r, func_decl_info(id, OP_0_PW_0_REAL));
|
||||
m_0_pw_0_real = m->mk_const(z_pw_z_real);
|
||||
m->inc_ref(m_0_pw_0_real);
|
||||
|
||||
MK_OP(m_neg_root_decl, "neg-root", OP_NEG_ROOT, r);
|
||||
MK_UNARY(m_div_0_decl, "/0", OP_DIV_0, r);
|
||||
MK_UNARY(m_idiv_0_decl, "div0", OP_IDIV_0, i);
|
||||
MK_UNARY(m_mod_0_decl, "mod0", OP_MOD_0, i);
|
||||
MK_UNARY(m_u_asin_decl, "asin-u", OP_U_ASIN, r);
|
||||
MK_UNARY(m_u_acos_decl, "acos-u", OP_U_ACOS, r);
|
||||
}
|
||||
|
@ -278,12 +269,7 @@ arith_decl_plugin::arith_decl_plugin():
|
|||
m_atanh_decl(0),
|
||||
m_pi(0),
|
||||
m_e(0),
|
||||
m_0_pw_0_int(0),
|
||||
m_0_pw_0_real(0),
|
||||
m_neg_root_decl(0),
|
||||
m_div_0_decl(0),
|
||||
m_idiv_0_decl(0),
|
||||
m_mod_0_decl(0),
|
||||
m_u_asin_decl(0),
|
||||
m_u_acos_decl(0),
|
||||
m_convert_int_numerals_to_real(false) {
|
||||
|
@ -338,12 +324,7 @@ void arith_decl_plugin::finalize() {
|
|||
DEC_REF(m_atanh_decl);
|
||||
DEC_REF(m_pi);
|
||||
DEC_REF(m_e);
|
||||
DEC_REF(m_0_pw_0_int);
|
||||
DEC_REF(m_0_pw_0_real);
|
||||
DEC_REF(m_neg_root_decl);
|
||||
DEC_REF(m_div_0_decl);
|
||||
DEC_REF(m_idiv_0_decl);
|
||||
DEC_REF(m_mod_0_decl);
|
||||
DEC_REF(m_u_asin_decl);
|
||||
DEC_REF(m_u_acos_decl);
|
||||
m_manager->dec_array_ref(m_small_ints.size(), m_small_ints.c_ptr());
|
||||
|
@ -391,18 +372,24 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
|
|||
case OP_ATANH: return m_atanh_decl;
|
||||
case OP_PI: return m_pi->get_decl();
|
||||
case OP_E: return m_e->get_decl();
|
||||
case OP_0_PW_0_INT: return m_0_pw_0_int->get_decl();
|
||||
case OP_0_PW_0_REAL: return m_0_pw_0_real->get_decl();
|
||||
//case OP_0_PW_0_INT: return m_0_pw_0_int->get_decl();
|
||||
//case OP_0_PW_0_REAL: return m_0_pw_0_real->get_decl();
|
||||
case OP_NEG_ROOT: return m_neg_root_decl;
|
||||
case OP_DIV_0: return m_div_0_decl;
|
||||
case OP_IDIV_0: return m_idiv_0_decl;
|
||||
case OP_MOD_0: return m_mod_0_decl;
|
||||
//case OP_DIV_0: return m_div_0_decl;
|
||||
//case OP_IDIV_0: return m_idiv_0_decl;
|
||||
//case OP_MOD_0: return m_mod_0_decl;
|
||||
case OP_U_ASIN: return m_u_asin_decl;
|
||||
case OP_U_ACOS: return m_u_acos_decl;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void arith_decl_plugin::check_arity(unsigned arity, unsigned expected_arity) {
|
||||
if (arity != expected_arity) {
|
||||
m_manager->raise_exception("invalid number of arguments passed to function");
|
||||
}
|
||||
}
|
||||
|
||||
inline decl_kind arith_decl_plugin::fix_kind(decl_kind k, unsigned arity) {
|
||||
if (k == OP_SUB && arity == 1) {
|
||||
return OP_UMINUS;
|
||||
|
@ -482,9 +469,9 @@ static bool has_real_arg(ast_manager * m, unsigned num_args, expr * const * args
|
|||
static bool is_const_op(decl_kind k) {
|
||||
return
|
||||
k == OP_PI ||
|
||||
k == OP_E ||
|
||||
k == OP_0_PW_0_INT ||
|
||||
k == OP_0_PW_0_REAL;
|
||||
k == OP_E;
|
||||
//k == OP_0_PW_0_INT ||
|
||||
//k == OP_0_PW_0_REAL;
|
||||
}
|
||||
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef ARITH_DECL_PLUGIN_H_
|
||||
#define ARITH_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
class sexpr;
|
||||
|
||||
namespace algebraic_numbers {
|
||||
|
@ -70,12 +70,7 @@ enum arith_op_kind {
|
|||
OP_PI,
|
||||
OP_E,
|
||||
// under-specified symbols
|
||||
OP_0_PW_0_INT, // 0^0 for integers
|
||||
OP_0_PW_0_REAL, // 0^0 for reals
|
||||
OP_NEG_ROOT, // x^n when n is even and x is negative
|
||||
OP_DIV_0, // x/0
|
||||
OP_IDIV_0, // x div 0
|
||||
OP_MOD_0, // x mod 0
|
||||
OP_U_ASIN, // asin(x) for x < -1 or x > 1
|
||||
OP_U_ACOS, // acos(x) for x < -1 or x > 1
|
||||
LAST_ARITH_OP
|
||||
|
@ -141,12 +136,7 @@ protected:
|
|||
app * m_pi;
|
||||
app * m_e;
|
||||
|
||||
app * m_0_pw_0_int;
|
||||
app * m_0_pw_0_real;
|
||||
func_decl * m_neg_root_decl;
|
||||
func_decl * m_div_0_decl;
|
||||
func_decl * m_idiv_0_decl;
|
||||
func_decl * m_mod_0_decl;
|
||||
func_decl * m_u_asin_decl;
|
||||
func_decl * m_u_acos_decl;
|
||||
ptr_vector<app> m_small_ints;
|
||||
|
@ -157,6 +147,7 @@ protected:
|
|||
func_decl * mk_func_decl(decl_kind k, bool is_real);
|
||||
virtual void set_manager(ast_manager * m, family_id id);
|
||||
decl_kind fix_kind(decl_kind k, unsigned arity);
|
||||
void check_arity(unsigned arity, unsigned expected_arity);
|
||||
func_decl * mk_num_decl(unsigned num_parameters, parameter const * parameters, unsigned arity);
|
||||
|
||||
public:
|
||||
|
@ -206,10 +197,6 @@ public:
|
|||
|
||||
app * mk_e() const { return m_e; }
|
||||
|
||||
app * mk_0_pw_0_int() const { return m_0_pw_0_int; }
|
||||
|
||||
app * mk_0_pw_0_real() const { return m_0_pw_0_real; }
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool is_considered_uninterpreted(func_decl * f) {
|
||||
|
@ -217,12 +204,7 @@ public:
|
|||
return false;
|
||||
switch (f->get_decl_kind())
|
||||
{
|
||||
case OP_0_PW_0_INT:
|
||||
case OP_0_PW_0_REAL:
|
||||
case OP_NEG_ROOT:
|
||||
case OP_DIV_0:
|
||||
case OP_IDIV_0:
|
||||
case OP_MOD_0:
|
||||
case OP_U_ASIN:
|
||||
case OP_U_ACOS:
|
||||
return true;
|
||||
|
@ -275,9 +257,9 @@ public:
|
|||
bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); }
|
||||
bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); }
|
||||
bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); }
|
||||
bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); }
|
||||
//bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); }
|
||||
bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); }
|
||||
bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); }
|
||||
//bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); }
|
||||
bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); }
|
||||
bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); }
|
||||
bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); }
|
||||
|
@ -388,16 +370,16 @@ public:
|
|||
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
|
||||
app * mk_gt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GT, arg1, arg2); }
|
||||
|
||||
app * mk_add(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
||||
app * mk_add(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
|
||||
app * mk_add(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
|
||||
app * mk_add(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
||||
app * mk_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
|
||||
app * mk_add(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
|
||||
|
||||
app * mk_sub(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
|
||||
app * mk_sub(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
|
||||
app * mk_mul(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
|
||||
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
|
||||
app * mk_mul(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
||||
app * mk_uminus(expr * arg) { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
|
||||
app * mk_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
|
||||
app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
|
||||
app * mk_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
|
||||
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
|
||||
app * mk_mul(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
||||
app * mk_uminus(expr * arg) const { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
|
||||
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV, arg1, arg2); }
|
||||
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
|
||||
app * mk_rem(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM, arg1, arg2); }
|
||||
|
@ -424,11 +406,6 @@ public:
|
|||
app * mk_pi() { return plugin().mk_pi(); }
|
||||
app * mk_e() { return plugin().mk_e(); }
|
||||
|
||||
app * mk_0_pw_0_int() { return plugin().mk_0_pw_0_int(); }
|
||||
app * mk_0_pw_0_real() { return plugin().mk_0_pw_0_real(); }
|
||||
app * mk_div0(expr * arg) { return m_manager.mk_app(m_afid, OP_DIV_0, arg); }
|
||||
app * mk_idiv0(expr * arg) { return m_manager.mk_app(m_afid, OP_IDIV_0, arg); }
|
||||
app * mk_mod0(expr * arg) { return m_manager.mk_app(m_afid, OP_MOD_0, arg); }
|
||||
app * mk_neg_root(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_NEG_ROOT, arg1, arg2); }
|
||||
app * mk_u_asin(expr * arg) { return m_manager.mk_app(m_afid, OP_U_ASIN, arg); }
|
||||
app * mk_u_acos(expr * arg) { return m_manager.mk_app(m_afid, OP_U_ACOS, arg); }
|
||||
|
|
|
@ -17,10 +17,10 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include<sstream>
|
||||
#include"array_decl_plugin.h"
|
||||
#include"warning.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "util/warning.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
|
||||
array_decl_plugin::array_decl_plugin():
|
||||
m_store_sym("store"),
|
||||
|
@ -546,7 +546,7 @@ expr * array_decl_plugin::get_some_value(sort * s) {
|
|||
return m_manager->mk_app(m_family_id, OP_CONST_ARRAY, 1, &p, 1, &v);
|
||||
}
|
||||
|
||||
bool array_decl_plugin::is_fully_interp(sort const * s) const {
|
||||
bool array_decl_plugin::is_fully_interp(sort * s) const {
|
||||
SASSERT(s->is_sort_of(m_family_id, ARRAY_SORT));
|
||||
unsigned sz = get_array_arity(s);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
|
@ -556,9 +556,9 @@ bool array_decl_plugin::is_fully_interp(sort const * s) const {
|
|||
return m_manager->is_fully_interp(get_array_range(s));
|
||||
}
|
||||
|
||||
func_decl * array_recognizers::get_as_array_func_decl(app * n) const {
|
||||
func_decl * array_recognizers::get_as_array_func_decl(expr * n) const {
|
||||
SASSERT(is_as_array(n));
|
||||
return to_func_decl(n->get_decl()->get_parameter(0).get_ast());
|
||||
return to_func_decl(to_app(n)->get_decl()->get_parameter(0).get_ast());
|
||||
}
|
||||
|
||||
array_util::array_util(ast_manager& m):
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef ARRAY_DECL_PLUGIN_H_
|
||||
#define ARRAY_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
|
||||
inline sort* get_array_range(sort const * s) {
|
||||
|
@ -127,7 +127,7 @@ class array_decl_plugin : public decl_plugin {
|
|||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool is_fully_interp(sort const * s) const;
|
||||
virtual bool is_fully_interp(sort * s) const;
|
||||
};
|
||||
|
||||
class array_recognizers {
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
|
||||
bool is_map(func_decl* f) const { return is_decl_of(f, m_fid, OP_ARRAY_MAP); }
|
||||
bool is_as_array(func_decl* f) const { return is_decl_of(f, m_fid, OP_AS_ARRAY); }
|
||||
func_decl * get_as_array_func_decl(app * n) const;
|
||||
func_decl * get_as_array_func_decl(expr * n) const;
|
||||
};
|
||||
|
||||
class array_util : public array_recognizers {
|
||||
|
|
116
src/ast/ast.cpp
116
src/ast/ast.cpp
|
@ -18,14 +18,14 @@ Revision History:
|
|||
--*/
|
||||
#include<sstream>
|
||||
#include<cstring>
|
||||
#include"ast.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"buffer.h"
|
||||
#include"warning.h"
|
||||
#include"string_buffer.h"
|
||||
#include"ast_util.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "util/buffer.h"
|
||||
#include "util/warning.h"
|
||||
#include "util/string_buffer.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -35,7 +35,7 @@ Revision History:
|
|||
|
||||
parameter::~parameter() {
|
||||
if (m_kind == PARAM_RATIONAL) {
|
||||
reinterpret_cast<rational *>(m_rational)->~rational();
|
||||
dealloc(m_rational);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,14 +50,14 @@ parameter& parameter::operator=(parameter const& other) {
|
|||
return *this;
|
||||
}
|
||||
if (m_kind == PARAM_RATIONAL) {
|
||||
reinterpret_cast<rational *>(m_rational)->~rational();
|
||||
dealloc(m_rational);
|
||||
}
|
||||
m_kind = other.m_kind;
|
||||
switch(other.m_kind) {
|
||||
case PARAM_INT: m_int = other.get_int(); break;
|
||||
case PARAM_AST: m_ast = other.get_ast(); break;
|
||||
case PARAM_SYMBOL: new (m_symbol) symbol(other.get_symbol()); break;
|
||||
case PARAM_RATIONAL: new (m_rational) rational(other.get_rational()); break;
|
||||
case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
|
||||
case PARAM_RATIONAL: m_rational = alloc(rational, other.get_rational()); break;
|
||||
case PARAM_DOUBLE: m_dval = other.m_dval; break;
|
||||
case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
|
||||
default:
|
||||
|
@ -188,18 +188,14 @@ decl_info::decl_info(decl_info const& other) :
|
|||
|
||||
|
||||
void decl_info::init_eh(ast_manager & m) {
|
||||
vector<parameter>::iterator it = m_parameters.begin();
|
||||
vector<parameter>::iterator end = m_parameters.end();
|
||||
for (; it != end; ++it) {
|
||||
it->init_eh(m);
|
||||
for (parameter & p : m_parameters) {
|
||||
p.init_eh(m);
|
||||
}
|
||||
}
|
||||
|
||||
void decl_info::del_eh(ast_manager & m) {
|
||||
vector<parameter>::iterator it = m_parameters.begin();
|
||||
vector<parameter>::iterator end = m_parameters.end();
|
||||
for (; it != end; ++it) {
|
||||
it->del_eh(m, m_family_id);
|
||||
for (parameter & p : m_parameters) {
|
||||
p.del_eh(m, m_family_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1291,10 +1287,8 @@ decl_kind user_sort_plugin::register_name(symbol s) {
|
|||
|
||||
decl_plugin * user_sort_plugin::mk_fresh() {
|
||||
user_sort_plugin * p = alloc(user_sort_plugin);
|
||||
svector<symbol>::iterator it = m_sort_names.begin();
|
||||
svector<symbol>::iterator end = m_sort_names.end();
|
||||
for (; it != end; ++it)
|
||||
p->register_name(*it);
|
||||
for (symbol const& s : m_sort_names)
|
||||
p->register_name(s);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -1414,26 +1408,20 @@ ast_manager::~ast_manager() {
|
|||
dec_ref(m_true);
|
||||
dec_ref(m_false);
|
||||
dec_ref(m_undef_proof);
|
||||
ptr_vector<decl_plugin>::iterator it = m_plugins.begin();
|
||||
ptr_vector<decl_plugin>::iterator end = m_plugins.end();
|
||||
for (; it != end; ++it) {
|
||||
if (*it)
|
||||
(*it)->finalize();
|
||||
for (decl_plugin* p : m_plugins) {
|
||||
if (p)
|
||||
p->finalize();
|
||||
}
|
||||
it = m_plugins.begin();
|
||||
for (; it != end; ++it) {
|
||||
if (*it)
|
||||
dealloc(*it);
|
||||
for (decl_plugin* p : m_plugins) {
|
||||
if (p)
|
||||
dealloc(p);
|
||||
}
|
||||
m_plugins.reset();
|
||||
while (!m_ast_table.empty()) {
|
||||
DEBUG_CODE(std::cout << "ast_manager LEAKED: " << m_ast_table.size() << std::endl;);
|
||||
ptr_vector<ast> roots;
|
||||
ast_mark mark;
|
||||
ast_table::iterator it_a = m_ast_table.begin();
|
||||
ast_table::iterator end_a = m_ast_table.end();
|
||||
for (; it_a != end_a; ++it_a) {
|
||||
ast* n = (*it_a);
|
||||
for (ast * n : m_ast_table) {
|
||||
switch (n->get_kind()) {
|
||||
case AST_SORT: {
|
||||
sort_info* info = to_sort(n)->get_info();
|
||||
|
@ -1466,9 +1454,7 @@ ast_manager::~ast_manager() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
it_a = m_ast_table.begin();
|
||||
for (; it_a != end_a; ++it_a) {
|
||||
ast* n = *it_a;
|
||||
for (ast * n : m_ast_table) {
|
||||
if (!mark.is_marked(n)) {
|
||||
roots.push_back(n);
|
||||
}
|
||||
|
@ -1543,12 +1529,15 @@ void ast_manager::raise_exception(char const * msg) {
|
|||
throw ast_exception(msg);
|
||||
}
|
||||
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
void ast_manager::copy_families_plugins(ast_manager const & from) {
|
||||
TRACE("copy_families_plugins",
|
||||
tout << "target:\n";
|
||||
for (family_id fid = 0; m_family_manager.has_family(fid); fid++) {
|
||||
tout << "fid: " << fid << " fidname: " << get_family_name(fid) << "\n";
|
||||
});
|
||||
ast_translation trans(const_cast<ast_manager&>(from), *this, false);
|
||||
for (family_id fid = 0; from.m_family_manager.has_family(fid); fid++) {
|
||||
SASSERT(from.is_builtin_family_id(fid) == is_builtin_family_id(fid));
|
||||
SASSERT(!from.is_builtin_family_id(fid) || m_family_manager.has_family(fid));
|
||||
|
@ -1569,6 +1558,9 @@ void ast_manager::copy_families_plugins(ast_manager const & from) {
|
|||
SASSERT(new_p->get_family_id() == fid);
|
||||
SASSERT(has_plugin(fid));
|
||||
}
|
||||
if (from.has_plugin(fid)) {
|
||||
get_plugin(fid)->inherit(from.get_plugin(fid), trans);
|
||||
}
|
||||
SASSERT(from.m_family_manager.has_family(fid) == m_family_manager.has_family(fid));
|
||||
SASSERT(from.get_family_id(fid_name) == get_family_id(fid_name));
|
||||
SASSERT(!from.has_plugin(fid) || has_plugin(fid));
|
||||
|
@ -1663,11 +1655,8 @@ bool ast_manager::is_bool(expr const * n) const {
|
|||
|
||||
#ifdef Z3DEBUG
|
||||
bool ast_manager::slow_not_contains(ast const * n) {
|
||||
ast_table::iterator it = m_ast_table.begin();
|
||||
ast_table::iterator end = m_ast_table.end();
|
||||
unsigned num = 0;
|
||||
for (; it != end; ++it) {
|
||||
ast * curr = *it;
|
||||
for (ast * curr : m_ast_table) {
|
||||
if (compare_nodes(curr, n)) {
|
||||
TRACE("nondet_bug",
|
||||
tout << "id1: " << curr->get_id() << ", id2: " << n->get_id() << "\n";
|
||||
|
@ -1935,6 +1924,35 @@ sort * ast_manager::mk_sort(symbol const & name, sort_info * info) {
|
|||
return register_node(new_node);
|
||||
}
|
||||
|
||||
sort * ast_manager::substitute(sort* s, unsigned n, sort * const * src, sort * const * dst) {
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
if (s == src[i]) return dst[i];
|
||||
}
|
||||
|
||||
vector<parameter> ps;
|
||||
bool change = false;
|
||||
sort_ref_vector sorts(*this);
|
||||
for (unsigned i = 0; i < s->get_num_parameters(); ++i) {
|
||||
parameter const& p = s->get_parameter(i);
|
||||
if (p.is_ast()) {
|
||||
SASSERT(is_sort(p.get_ast()));
|
||||
change = true;
|
||||
sorts.push_back(substitute(to_sort(p.get_ast()), n, src, dst));
|
||||
ps.push_back(parameter(sorts.back()));
|
||||
}
|
||||
else {
|
||||
ps.push_back(p);
|
||||
}
|
||||
}
|
||||
if (!change) {
|
||||
return s;
|
||||
}
|
||||
decl_info dinfo(s->get_family_id(), s->get_decl_kind(), ps.size(), ps.c_ptr(), s->private_parameters());
|
||||
sort_info sinfo(dinfo, s->get_num_elements());
|
||||
return mk_sort(s->get_name(), &sinfo);
|
||||
}
|
||||
|
||||
|
||||
sort * ast_manager::mk_uninterpreted_sort(symbol const & name, unsigned num_parameters, parameter const * parameters) {
|
||||
user_sort_plugin * plugin = get_user_sort_plugin();
|
||||
decl_kind kind = plugin->register_name(name);
|
||||
|
@ -2177,7 +2195,10 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar
|
|||
throw ast_exception(buffer.str().c_str());
|
||||
}
|
||||
app * r = 0;
|
||||
if (num_args > 2 && !decl->is_flat_associative()) {
|
||||
if (num_args == 1 && decl->is_chainable() && decl->get_arity() == 2) {
|
||||
r = mk_true();
|
||||
}
|
||||
else if (num_args > 2 && !decl->is_flat_associative()) {
|
||||
if (decl->is_right_associative()) {
|
||||
unsigned j = num_args - 1;
|
||||
r = mk_app_core(decl, args[j-1], args[j]);
|
||||
|
@ -2206,7 +2227,7 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar
|
|||
r = mk_app_core(decl, num_args, args);
|
||||
}
|
||||
SASSERT(r != 0);
|
||||
TRACE("app_ground", tout << "ground: " << r->is_ground() << "\n" << mk_ll_pp(r, *this) << "\n";);
|
||||
TRACE("app_ground", tout << "ground: " << r->is_ground() << " id: " << r->get_id() << "\n" << mk_ll_pp(r, *this) << "\n";);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2351,6 +2372,7 @@ quantifier * ast_manager::mk_quantifier(bool forall, unsigned num_decls, sort *
|
|||
SASSERT(num_decls > 0);
|
||||
DEBUG_CODE({
|
||||
for (unsigned i = 0; i < num_patterns; ++i) {
|
||||
TRACE("ast", tout << i << " " << mk_pp(patterns[i], *this) << "\n";);
|
||||
SASSERT(is_pattern(patterns[i]));
|
||||
}});
|
||||
unsigned sz = quantifier::get_obj_size(num_decls, num_patterns, num_no_patterns);
|
||||
|
@ -2576,7 +2598,7 @@ expr * ast_manager::get_some_value(sort * s) {
|
|||
return mk_model_value(0, s);
|
||||
}
|
||||
|
||||
bool ast_manager::is_fully_interp(sort const * s) const {
|
||||
bool ast_manager::is_fully_interp(sort * s) const {
|
||||
if (is_uninterp(s))
|
||||
return false;
|
||||
family_id fid = s->get_family_id();
|
||||
|
|
|
@ -19,32 +19,32 @@ Revision History:
|
|||
#ifndef AST_H_
|
||||
#define AST_H_
|
||||
|
||||
#include"vector.h"
|
||||
#include"hashtable.h"
|
||||
#include"buffer.h"
|
||||
#include"symbol.h"
|
||||
#include"rational.h"
|
||||
#include"hash.h"
|
||||
#include"optional.h"
|
||||
#include"trace.h"
|
||||
#include"bit_vector.h"
|
||||
#include"symbol_table.h"
|
||||
#include"tptr.h"
|
||||
#include"memory_manager.h"
|
||||
#include"small_object_allocator.h"
|
||||
#include"obj_ref.h"
|
||||
#include"ref_vector.h"
|
||||
#include"ref_buffer.h"
|
||||
#include"obj_mark.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"id_gen.h"
|
||||
#include"map.h"
|
||||
#include"parray.h"
|
||||
#include"dictionary.h"
|
||||
#include"chashtable.h"
|
||||
#include"z3_exception.h"
|
||||
#include"dependency.h"
|
||||
#include"rlimit.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/hashtable.h"
|
||||
#include "util/buffer.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/rational.h"
|
||||
#include "util/hash.h"
|
||||
#include "util/optional.h"
|
||||
#include "util/trace.h"
|
||||
#include "util/bit_vector.h"
|
||||
#include "util/symbol_table.h"
|
||||
#include "util/tptr.h"
|
||||
#include "util/memory_manager.h"
|
||||
#include "util/small_object_allocator.h"
|
||||
#include "util/obj_ref.h"
|
||||
#include "util/ref_vector.h"
|
||||
#include "util/ref_buffer.h"
|
||||
#include "util/obj_mark.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "util/id_gen.h"
|
||||
#include "util/map.h"
|
||||
#include "util/parray.h"
|
||||
#include "util/dictionary.h"
|
||||
#include "util/chashtable.h"
|
||||
#include "util/z3_exception.h"
|
||||
#include "util/dependency.h"
|
||||
#include "util/rlimit.h"
|
||||
|
||||
#define RECYCLE_FREE_AST_INDICES
|
||||
|
||||
|
@ -102,8 +102,8 @@ private:
|
|||
union {
|
||||
int m_int; // for PARAM_INT
|
||||
ast* m_ast; // for PARAM_AST
|
||||
char m_symbol[sizeof(symbol)]; // for PARAM_SYMBOL
|
||||
char m_rational[sizeof(rational)]; // for PARAM_RATIONAL
|
||||
void const* m_symbol; // for PARAM_SYMBOL
|
||||
rational* m_rational; // for PARAM_RATIONAL
|
||||
double m_dval; // for PARAM_DOUBLE (remark: this is not used in float_decl_plugin)
|
||||
unsigned m_ext_id; // for PARAM_EXTERNAL
|
||||
};
|
||||
|
@ -114,12 +114,10 @@ public:
|
|||
explicit parameter(int val): m_kind(PARAM_INT), m_int(val) {}
|
||||
explicit parameter(unsigned val): m_kind(PARAM_INT), m_int(val) {}
|
||||
explicit parameter(ast * p): m_kind(PARAM_AST), m_ast(p) {}
|
||||
explicit parameter(symbol const & s): m_kind(PARAM_SYMBOL) { new (m_symbol) symbol(s); }
|
||||
explicit parameter(rational const & r): m_kind(PARAM_RATIONAL) { new (m_rational) rational(r); }
|
||||
explicit parameter(symbol const & s): m_kind(PARAM_SYMBOL), m_symbol(s.c_ptr()) {}
|
||||
explicit parameter(rational const & r): m_kind(PARAM_RATIONAL), m_rational(alloc(rational, r)) {}
|
||||
explicit parameter(double d):m_kind(PARAM_DOUBLE), m_dval(d) {}
|
||||
explicit parameter(const char *s):m_kind(PARAM_SYMBOL) {
|
||||
new (m_symbol) symbol(s);
|
||||
}
|
||||
explicit parameter(const char *s):m_kind(PARAM_SYMBOL), m_symbol(symbol(s).c_ptr()) {}
|
||||
explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}
|
||||
parameter(parameter const&);
|
||||
|
||||
|
@ -156,8 +154,8 @@ public:
|
|||
|
||||
int get_int() const { SASSERT(is_int()); return m_int; }
|
||||
ast * get_ast() const { SASSERT(is_ast()); return m_ast; }
|
||||
symbol const & get_symbol() const { SASSERT(is_symbol()); return *(reinterpret_cast<const symbol *>(m_symbol)); }
|
||||
rational const & get_rational() const { SASSERT(is_rational()); return *(reinterpret_cast<const rational *>(m_rational)); }
|
||||
symbol get_symbol() const { SASSERT(is_symbol()); return symbol::mk_symbol_from_c_ptr(m_symbol); }
|
||||
rational const & get_rational() const { SASSERT(is_rational()); return *m_rational; }
|
||||
double get_double() const { SASSERT(is_double()); return m_dval; }
|
||||
unsigned get_ext_id() const { SASSERT(is_external()); return m_ext_id; }
|
||||
|
||||
|
@ -337,13 +335,17 @@ public:
|
|||
unsigned num_parameters = 0, parameter const * parameters = 0, bool private_parameters = false):
|
||||
decl_info(family_id, k, num_parameters, parameters, private_parameters), m_num_elements(num_elements) {
|
||||
}
|
||||
sort_info(sort_info const& other) : decl_info(other), m_num_elements(other.m_num_elements) {
|
||||
sort_info(sort_info const& other) : decl_info(other), m_num_elements(other.m_num_elements) {
|
||||
}
|
||||
sort_info(decl_info const& di, sort_size const& num_elements) :
|
||||
decl_info(di), m_num_elements(num_elements) {}
|
||||
|
||||
~sort_info() {}
|
||||
|
||||
bool is_infinite() const { return m_num_elements.is_infinite(); }
|
||||
bool is_very_big() const { return m_num_elements.is_very_big(); }
|
||||
sort_size const & get_num_elements() const { return m_num_elements; }
|
||||
void set_num_elements(sort_size const& s) { m_num_elements = s; }
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, sort_info const & info);
|
||||
|
@ -569,6 +571,7 @@ public:
|
|||
bool is_very_big() const { return get_info() == 0 || get_info()->is_very_big(); }
|
||||
bool is_sort_of(family_id fid, decl_kind k) const { return get_family_id() == fid && get_decl_kind() == k; }
|
||||
sort_size const & get_num_elements() const { return get_info()->get_num_elements(); }
|
||||
void set_num_elements(sort_size const& s) { get_info()->set_num_elements(s); }
|
||||
unsigned get_size() const { return get_obj_size(); }
|
||||
};
|
||||
|
||||
|
@ -892,6 +895,8 @@ struct ast_eq_proc {
|
|||
}
|
||||
};
|
||||
|
||||
class ast_translation;
|
||||
|
||||
class ast_table : public chashtable<ast*, obj_ptr_hash<ast>, ast_eq_proc> {
|
||||
public:
|
||||
void erase(ast * n);
|
||||
|
@ -927,6 +932,8 @@ protected:
|
|||
m_family_id = id;
|
||||
}
|
||||
|
||||
virtual void inherit(decl_plugin* other_p, ast_translation& ) { }
|
||||
|
||||
friend class ast_manager;
|
||||
|
||||
public:
|
||||
|
@ -990,7 +997,7 @@ public:
|
|||
|
||||
// Return true if the interpreted sort s does not depend on uninterpreted sorts.
|
||||
// This may be the case, for example, for array and datatype sorts.
|
||||
virtual bool is_fully_interp(sort const * s) const { return true; }
|
||||
virtual bool is_fully_interp(sort * s) const { return true; }
|
||||
|
||||
// Event handlers for deleting/translating PARAM_EXTERNAL
|
||||
virtual void del(parameter const & p) {}
|
||||
|
@ -1657,6 +1664,8 @@ public:
|
|||
|
||||
sort * mk_sort(family_id fid, decl_kind k, unsigned num_parameters = 0, parameter const * parameters = 0);
|
||||
|
||||
sort * substitute(sort* s, unsigned n, sort * const * src, sort * const * dst);
|
||||
|
||||
sort * mk_bool_sort() const { return m_bool_sort; }
|
||||
|
||||
sort * mk_proof_sort() const { return m_proof_sort; }
|
||||
|
@ -1669,7 +1678,7 @@ public:
|
|||
\brief A sort is "fully" interpreted if it is interpreted,
|
||||
and doesn't depend on other uninterpreted sorts.
|
||||
*/
|
||||
bool is_fully_interp(sort const * s) const;
|
||||
bool is_fully_interp(sort * s) const;
|
||||
|
||||
func_decl * mk_func_decl(family_id fid, decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range = 0);
|
||||
|
@ -2021,8 +2030,8 @@ public:
|
|||
app * mk_not(expr * n) { return mk_app(m_basic_family_id, OP_NOT, n); }
|
||||
app * mk_distinct(unsigned num_args, expr * const * args);
|
||||
app * mk_distinct_expanded(unsigned num_args, expr * const * args);
|
||||
app * mk_true() { return m_true; }
|
||||
app * mk_false() { return m_false; }
|
||||
app * mk_true() const { return m_true; }
|
||||
app * mk_false() const { return m_false; }
|
||||
app * mk_bool_val(bool b) { return b?m_true:m_false; }
|
||||
app * mk_interp(expr * arg) { return mk_app(m_basic_family_id, OP_INTERP, arg); }
|
||||
|
||||
|
@ -2472,6 +2481,7 @@ public:
|
|||
void operator()(AST * n) { m_manager.inc_ref(n); }
|
||||
};
|
||||
|
||||
|
||||
#endif /* AST_H_ */
|
||||
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ Revision History:
|
|||
--*/
|
||||
|
||||
#include<iostream>
|
||||
#include"for_each_ast.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include "ast/for_each_ast.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
|
||||
// #define AST_LL_PP_SHOW_FAMILY_NAME
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef AST_LL_PP_H_
|
||||
#define AST_LL_PP_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
#include<iostream>
|
||||
|
||||
void ast_ll_pp(std::ostream & out, ast_manager & m, ast * n, bool only_exprs=true, bool compact=true);
|
||||
|
|
|
@ -16,7 +16,7 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"ast.h"
|
||||
#include "ast/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
|
||||
|
|
|
@ -21,7 +21,7 @@ Revision History:
|
|||
#ifndef AST_PP_H_
|
||||
#define AST_PP_H_
|
||||
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
struct mk_pp : public mk_ismt2_pp {
|
||||
mk_pp(ast * t, ast_manager & m, params_ref const & p, unsigned indent = 0, unsigned num_vars = 0, char const * var_prefix = 0):
|
||||
|
|
|
@ -17,9 +17,9 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include "ast_pp_util.h"
|
||||
#include "ast_smt2_pp.h"
|
||||
#include "ast_smt_pp.h"
|
||||
#include "ast/ast_pp_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_smt_pp.h"
|
||||
|
||||
void ast_pp_util::collect(expr* e) {
|
||||
coll.visit(e);
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef AST_PP_UTIL_H_
|
||||
#define AST_PP_UTIL_H_
|
||||
|
||||
#include "decl_collector.h"
|
||||
#include "ast/decl_collector.h"
|
||||
|
||||
class ast_pp_util {
|
||||
ast_manager& m;
|
||||
|
|
|
@ -16,8 +16,8 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"ast_printer.h"
|
||||
#include"pp.h"
|
||||
#include "ast/ast_printer.h"
|
||||
#include "ast/pp.h"
|
||||
|
||||
class simple_ast_printer_context : public ast_printer_context {
|
||||
ast_manager & m_manager;
|
||||
|
|
|
@ -19,8 +19,8 @@ Revision History:
|
|||
#ifndef AST_PRINTER_H_
|
||||
#define AST_PRINTER_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
class ast_printer {
|
||||
public:
|
||||
|
|
|
@ -18,13 +18,13 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"shared_occs.h"
|
||||
#include"pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include"algebraic_numbers.h"
|
||||
#include"pp_params.hpp"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/shared_occs.h"
|
||||
#include "ast/pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "math/polynomial/algebraic_numbers.h"
|
||||
#include "ast/pp_params.hpp"
|
||||
using namespace format_ns;
|
||||
|
||||
#define ALIAS_PREFIX "a"
|
||||
|
@ -43,6 +43,9 @@ format * smt2_pp_environment::pp_fdecl_name(symbol const & s, unsigned & len) co
|
|||
len = static_cast<unsigned>(str.length());
|
||||
return mk_string(m, str.c_str());
|
||||
}
|
||||
else if (!s.bare_str()) {
|
||||
return mk_string(m, "null");
|
||||
}
|
||||
else {
|
||||
len = static_cast<unsigned>(strlen(s.bare_str()));
|
||||
return mk_string(m, s.bare_str());
|
||||
|
@ -431,16 +434,16 @@ format_ns::format * smt2_pp_environment::pp_sort(sort * s) {
|
|||
fs.push_back(pp_sort(to_sort(s->get_parameter(0).get_ast())));
|
||||
return mk_seq1(m, fs.begin(), fs.end(), f2f(), get_sutil().is_seq(s)?"Seq":"RegEx");
|
||||
}
|
||||
#if 0
|
||||
if (get_dtutil().is_datatype(s)) {
|
||||
ptr_buffer<format> fs;
|
||||
unsigned sz = get_dtutil().get_datatype_num_parameter_sorts(s);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
fs.push_back(pp_sort(get_dtutil().get_datatype_parameter_sort(s, i)));
|
||||
if (sz > 0) {
|
||||
ptr_buffer<format> fs;
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
fs.push_back(pp_sort(get_dtutil().get_datatype_parameter_sort(s, i)));
|
||||
}
|
||||
return mk_seq1(m, fs.begin(), fs.end(), f2f(), s->get_name().str().c_str());
|
||||
}
|
||||
return mk_seq1(m, fs.begin(), fs.end(), f2f(), s->get_name().str().c_str());
|
||||
}
|
||||
#endif
|
||||
return format_ns::mk_string(get_manager(), s->get_name().str().c_str());
|
||||
}
|
||||
|
||||
|
@ -1222,15 +1225,15 @@ mk_ismt2_pp::mk_ismt2_pp(ast * t, ast_manager & m, unsigned indent, unsigned num
|
|||
|
||||
std::ostream& operator<<(std::ostream& out, mk_ismt2_pp const & p) {
|
||||
smt2_pp_environment_dbg env(p.m_manager);
|
||||
if (is_expr(p.m_ast)) {
|
||||
if (p.m_ast == 0) {
|
||||
out << "null";
|
||||
}
|
||||
else if (is_expr(p.m_ast)) {
|
||||
ast_smt2_pp(out, to_expr(p.m_ast), env, p.m_params, p.m_indent, p.m_num_vars, p.m_var_prefix);
|
||||
}
|
||||
else if (is_sort(p.m_ast)) {
|
||||
ast_smt2_pp(out, to_sort(p.m_ast), env, p.m_params, p.m_indent);
|
||||
}
|
||||
else if (p.m_ast == 0) {
|
||||
out << "null";
|
||||
}
|
||||
else {
|
||||
SASSERT(is_func_decl(p.m_ast));
|
||||
ast_smt2_pp(out, to_func_decl(p.m_ast), env, p.m_params, p.m_indent);
|
||||
|
|
|
@ -22,16 +22,16 @@ Revision History:
|
|||
#ifndef AST_SMT2_PP_H_
|
||||
#define AST_SMT2_PP_H_
|
||||
|
||||
#include"format.h"
|
||||
#include"params.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"fpa_decl_plugin.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"seq_decl_plugin.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"smt2_util.h"
|
||||
#include "ast/format.h"
|
||||
#include "util/params.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/dl_decl_plugin.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "util/smt2_util.h"
|
||||
|
||||
class smt2_pp_environment {
|
||||
protected:
|
||||
|
|
|
@ -21,17 +21,17 @@ Revision History:
|
|||
|
||||
#include<sstream>
|
||||
#include<iostream>
|
||||
#include"ast_smt_pp.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"fpa_decl_plugin.h"
|
||||
#include"vector.h"
|
||||
#include"for_each_ast.h"
|
||||
#include"decl_collector.h"
|
||||
#include"smt2_util.h"
|
||||
#include"seq_decl_plugin.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/smt2_util.h"
|
||||
#include "ast/ast_smt_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/for_each_ast.h"
|
||||
#include "ast/decl_collector.h"
|
||||
|
||||
// ---------------------------------------
|
||||
// smt_renaming
|
||||
|
@ -174,7 +174,6 @@ class smt_printer {
|
|||
symbol m_logic;
|
||||
symbol m_AUFLIRA;
|
||||
bool m_no_lets;
|
||||
bool m_is_smt2;
|
||||
bool m_simplify_implies;
|
||||
expr* m_top;
|
||||
|
||||
|
@ -199,37 +198,30 @@ class smt_printer {
|
|||
}
|
||||
|
||||
void pp_id(expr* n) {
|
||||
if (m_is_smt2) {
|
||||
m_out << (is_bool(n)?"$x":(is_proof(n)?"@x":"?x")) << n->get_id();
|
||||
}
|
||||
else {
|
||||
m_out << (is_bool(n)?"$x":"?x") << n->get_id();
|
||||
}
|
||||
m_out << (is_bool(n)?"$x":(is_proof(n)?"@x":"?x")) << n->get_id();
|
||||
}
|
||||
|
||||
void pp_decl(func_decl* d) {
|
||||
symbol sym = m_renaming.get_symbol(d->get_name());
|
||||
if (d->get_family_id() == m_dt_fid) {
|
||||
m_out << sym;
|
||||
}
|
||||
else if (m_manager.is_ite(d)) {
|
||||
if (!m_is_smt2 && is_bool(d->get_range())) {
|
||||
m_out << "if_then_else";
|
||||
datatype_util util(m_manager);
|
||||
if (util.is_recognizer(d)) {
|
||||
visit_params(false, sym, d->get_num_parameters(), d->get_parameters());
|
||||
}
|
||||
else {
|
||||
m_out << "ite";
|
||||
m_out << sym;
|
||||
}
|
||||
}
|
||||
else if (!m_is_smt2 && m_manager.is_implies(d)) {
|
||||
m_out << "implies";
|
||||
else if (m_manager.is_ite(d)) {
|
||||
m_out << "ite";
|
||||
}
|
||||
else if (m_is_smt2 && m_manager.is_iff(d)) {
|
||||
else if (m_manager.is_iff(d)) {
|
||||
m_out << "=";
|
||||
}
|
||||
else if (m_is_smt2 && m_manager.is_implies(d)) {
|
||||
else if (m_manager.is_implies(d)) {
|
||||
m_out << "=>";
|
||||
}
|
||||
else if (m_is_smt2 && is_decl_of(d, m_arith_fid, OP_UMINUS)) {
|
||||
else if (is_decl_of(d, m_arith_fid, OP_UMINUS)) {
|
||||
m_out << "-";
|
||||
}
|
||||
else {
|
||||
|
@ -251,28 +243,23 @@ class smt_printer {
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_is_smt2) {
|
||||
if (is_sort_symbol && sym == symbol("String")) {
|
||||
m_out << "String";
|
||||
return;
|
||||
}
|
||||
if (is_sort_symbol &&
|
||||
sym != symbol("BitVec") &&
|
||||
sym != symbol("FloatingPoint") &&
|
||||
sym != symbol("RoundingMode")) {
|
||||
m_out << "(" << sym << " ";
|
||||
}
|
||||
else if (!is_sort_symbol && is_sort_param(num_params, params)) {
|
||||
m_out << "(as " << sym << " ";
|
||||
}
|
||||
else {
|
||||
m_out << "(_ " << sym << " ";
|
||||
}
|
||||
if (is_sort_symbol && sym == symbol("String")) {
|
||||
m_out << "String";
|
||||
return;
|
||||
}
|
||||
if (is_sort_symbol &&
|
||||
sym != symbol("BitVec") &&
|
||||
sym != symbol("FloatingPoint") &&
|
||||
sym != symbol("RoundingMode")) {
|
||||
m_out << "(" << sym << " ";
|
||||
}
|
||||
else if (!is_sort_symbol && is_sort_param(num_params, params)) {
|
||||
m_out << "(as " << sym << " ";
|
||||
}
|
||||
else {
|
||||
m_out << sym << "[";
|
||||
m_out << "(_ " << sym << " ";
|
||||
}
|
||||
|
||||
|
||||
for (unsigned i = 0; i < num_params; ++i) {
|
||||
parameter const& p = params[i];
|
||||
if (p.is_ast()) {
|
||||
|
@ -293,20 +280,10 @@ class smt_printer {
|
|||
m_out << p;
|
||||
}
|
||||
if (i + 1 < num_params) {
|
||||
if (m_is_smt2) {
|
||||
m_out << " ";
|
||||
}
|
||||
else {
|
||||
m_out << ": ";
|
||||
}
|
||||
m_out << " ";
|
||||
}
|
||||
}
|
||||
if (m_is_smt2) {
|
||||
m_out << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "]";
|
||||
}
|
||||
m_out << ")";
|
||||
}
|
||||
|
||||
bool is_auflira() const {
|
||||
|
@ -315,9 +292,7 @@ class smt_printer {
|
|||
|
||||
void visit_sort(sort* s, bool bool2int = false) {
|
||||
symbol sym;
|
||||
if (bool2int && is_bool(s) && !m_is_smt2) {
|
||||
sym = symbol("Int");
|
||||
} else if (s->is_sort_of(m_bv_fid, BV_SORT)) {
|
||||
if (s->is_sort_of(m_bv_fid, BV_SORT)) {
|
||||
sym = symbol("BitVec");
|
||||
}
|
||||
else if (s->is_sort_of(m_arith_fid, REAL_SORT)) {
|
||||
|
@ -329,51 +304,16 @@ class smt_printer {
|
|||
else if (s->is_sort_of(m_arith_fid, INT_SORT)) {
|
||||
sym = s->get_name();
|
||||
}
|
||||
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && m_is_smt2) {
|
||||
else if (s->is_sort_of(m_array_fid, ARRAY_SORT)) {
|
||||
sym = "Array";
|
||||
}
|
||||
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && !m_is_smt2) {
|
||||
unsigned num_params = s->get_num_parameters();
|
||||
SASSERT(num_params >= 2);
|
||||
if (is_auflira()) {
|
||||
sort* rng = to_sort(s->get_parameter(1).get_ast());
|
||||
if (rng->get_family_id() == m_array_fid) {
|
||||
m_out << "Array2";
|
||||
}
|
||||
else {
|
||||
m_out << "Array1";
|
||||
}
|
||||
return;
|
||||
}
|
||||
sort* s1 = to_sort(s->get_parameter(0).get_ast());
|
||||
sort* s2 = to_sort(s->get_parameter(1).get_ast());
|
||||
if (num_params == 2 &&
|
||||
s1->is_sort_of(m_bv_fid, BV_SORT) &&
|
||||
s2->is_sort_of(m_bv_fid, BV_SORT)) {
|
||||
m_out << "Array";
|
||||
m_out << "[" << s1->get_parameter(0).get_int();
|
||||
m_out << ":" << s2->get_parameter(0).get_int() << "]";
|
||||
return;
|
||||
}
|
||||
m_out << "(Array ";
|
||||
for (unsigned i = 0; i < num_params; ++i) {
|
||||
visit_sort(to_sort(s->get_parameter(i).get_ast()));
|
||||
if (i + 1 < num_params) {
|
||||
m_out << " ";
|
||||
}
|
||||
}
|
||||
m_out << ")";
|
||||
return;
|
||||
}
|
||||
else if (s->is_sort_of(m_dt_fid, DATATYPE_SORT)) {
|
||||
m_out << m_renaming.get_symbol(s->get_name());
|
||||
#if 0
|
||||
datatype_util util(m_manager);
|
||||
unsigned num_sorts = util.get_datatype_num_parameter_sorts(s);
|
||||
if (num_sorts > 0) {
|
||||
m_out << "(";
|
||||
}
|
||||
|
||||
m_out << m_renaming.get_symbol(s->get_name());
|
||||
if (num_sorts > 0) {
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
m_out << " ";
|
||||
|
@ -381,7 +321,6 @@ class smt_printer {
|
|||
}
|
||||
m_out << ")";
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -403,20 +342,7 @@ class smt_printer {
|
|||
|
||||
void pp_arg(expr *arg, app *parent)
|
||||
{
|
||||
if (!m_is_smt2 && is_bool(arg) && is_var(arg) && parent->get_family_id() == m_basic_fid) {
|
||||
m_out << "(not (= ";
|
||||
pp_marked_expr(arg);
|
||||
m_out << " 0))";
|
||||
} else if (!m_is_smt2 && is_bool(arg) && !is_var(arg) &&
|
||||
parent->get_family_id() != m_basic_fid &&
|
||||
parent->get_family_id() != m_dt_fid) {
|
||||
|
||||
m_out << "(ite ";
|
||||
pp_marked_expr(arg);
|
||||
m_out << " 1 0)";
|
||||
} else {
|
||||
pp_marked_expr(arg);
|
||||
}
|
||||
pp_marked_expr(arg);
|
||||
}
|
||||
|
||||
void visit_app(app* n) {
|
||||
|
@ -431,12 +357,7 @@ class smt_printer {
|
|||
if (m_autil.is_numeral(n, val, is_int)) {
|
||||
if (val.is_neg()) {
|
||||
val.neg();
|
||||
if (m_is_smt2) {
|
||||
m_out << "(- ";
|
||||
}
|
||||
else {
|
||||
m_out << "(~ ";
|
||||
}
|
||||
m_out << "(- ";
|
||||
display_rational(val, is_int);
|
||||
m_out << ")";
|
||||
}
|
||||
|
@ -458,12 +379,7 @@ class smt_printer {
|
|||
m_out << "\"";
|
||||
}
|
||||
else if (m_bvutil.is_numeral(n, val, bv_size)) {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(_ bv" << val << " " << bv_size << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "bv" << val << "[" << bv_size << "]";
|
||||
}
|
||||
m_out << "(_ bv" << val << " " << bv_size << ")";
|
||||
}
|
||||
else if (m_futil.is_numeral(n, float_val)) {
|
||||
m_out << "((_ to_fp " <<
|
||||
|
@ -473,37 +389,17 @@ class smt_printer {
|
|||
}
|
||||
else if (m_bvutil.is_bit2bool(n)) {
|
||||
unsigned bit = n->get_decl()->get_parameter(0).get_int();
|
||||
if (m_is_smt2) {
|
||||
m_out << "(= ((_ extract " << bit << " " << bit << ") ";
|
||||
pp_marked_expr(n->get_arg(0));
|
||||
m_out << ") (_ bv1 1))";
|
||||
}
|
||||
else {
|
||||
m_out << "(= (extract[" << bit << ":" << bit << "] ";
|
||||
pp_marked_expr(n->get_arg(0));
|
||||
m_out << ") bv1[1])";
|
||||
}
|
||||
m_out << "(= ((_ extract " << bit << " " << bit << ") ";
|
||||
pp_marked_expr(n->get_arg(0));
|
||||
m_out << ") (_ bv1 1))";
|
||||
}
|
||||
else if (m_manager.is_label(n, pos, names) && names.size() >= 1) {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(! ";
|
||||
pp_marked_expr(n->get_arg(0));
|
||||
m_out << (pos?":lblpos":":lblneg") << " " << m_renaming.get_symbol(names[0]) << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "(" << (pos?"lblpos":"lblneg") << " " << m_renaming.get_symbol(names[0]) << " ";
|
||||
expr* ch = n->get_arg(0);
|
||||
pp_marked_expr(ch);
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << "(! ";
|
||||
pp_marked_expr(n->get_arg(0));
|
||||
m_out << (pos?":lblpos":":lblneg") << " " << m_renaming.get_symbol(names[0]) << ")";
|
||||
}
|
||||
else if (m_manager.is_label_lit(n, names) && names.size() >= 1) {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(! true :lblpos " << m_renaming.get_symbol(names[0]) << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "(lblpos " << m_renaming.get_symbol(names[0]) << " true )";
|
||||
}
|
||||
m_out << "(! true :lblpos " << m_renaming.get_symbol(names[0]) << ")";
|
||||
}
|
||||
else if (num_args == 0) {
|
||||
if (decl->private_parameters()) {
|
||||
|
@ -533,7 +429,8 @@ class smt_printer {
|
|||
pp_arg(curr, n);
|
||||
m_out << ")";
|
||||
|
||||
} else if (m_manager.is_distinct(decl)) {
|
||||
}
|
||||
else if (m_manager.is_distinct(decl)) {
|
||||
ptr_vector<expr> args(num_args, n->get_args());
|
||||
unsigned idx = 0;
|
||||
m_out << "(and";
|
||||
|
@ -581,14 +478,11 @@ class smt_printer {
|
|||
|
||||
void print_no_lets(expr *e)
|
||||
{
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, true, m_simplify_implies, m_is_smt2, m_indent, m_num_var_names, m_var_names);
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, true, m_simplify_implies, true, m_indent, m_num_var_names, m_var_names);
|
||||
p(e);
|
||||
}
|
||||
|
||||
void print_bound(symbol const& name) {
|
||||
if (!m_is_smt2 && (name.is_numerical() || '?' != name.bare_str()[0])) {
|
||||
m_out << "?";
|
||||
}
|
||||
m_out << name;
|
||||
}
|
||||
|
||||
|
@ -602,9 +496,7 @@ class smt_printer {
|
|||
else {
|
||||
m_out << "exists ";
|
||||
}
|
||||
if (m_is_smt2) {
|
||||
m_out << "(";
|
||||
}
|
||||
m_out << "(";
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
sort* s = q->get_decl_sort(i);
|
||||
m_out << "(";
|
||||
|
@ -613,15 +505,13 @@ class smt_printer {
|
|||
visit_sort(s, true);
|
||||
m_out << ") ";
|
||||
}
|
||||
if (m_is_smt2) {
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << ")";
|
||||
|
||||
if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
if ((q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
m_out << "(! ";
|
||||
}
|
||||
{
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, m_is_smt2, m_simplify_implies, m_indent, m_num_var_names, m_var_names);
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, true, m_simplify_implies, m_indent, m_num_var_names, m_var_names);
|
||||
p(q->get_expr());
|
||||
}
|
||||
|
||||
|
@ -640,28 +530,18 @@ class smt_printer {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_is_smt2) {
|
||||
m_out << " :pattern ( ";
|
||||
}
|
||||
else {
|
||||
m_out << " :pat { ";
|
||||
}
|
||||
m_out << " :pattern ( ";
|
||||
for (unsigned j = 0; j < pat->get_num_args(); ++j) {
|
||||
print_no_lets(pat->get_arg(j));
|
||||
m_out << " ";
|
||||
}
|
||||
if (m_is_smt2) {
|
||||
m_out << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "}";
|
||||
}
|
||||
m_out << ")";
|
||||
}
|
||||
|
||||
if (q->get_qid() != symbol::null)
|
||||
m_out << " :qid " << q->get_qid();
|
||||
|
||||
if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
if ((q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << ")";
|
||||
|
@ -725,21 +605,11 @@ class smt_printer {
|
|||
}
|
||||
|
||||
void visit_expr(expr* n) {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(let ((";
|
||||
}
|
||||
else if (is_bool(n)) {
|
||||
m_out << "(flet (";
|
||||
}
|
||||
else {
|
||||
m_out << "(let (";
|
||||
}
|
||||
m_out << "(let ((";
|
||||
pp_id(n);
|
||||
m_out << " ";
|
||||
pp_expr(n);
|
||||
if (m_is_smt2) {
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << ")";
|
||||
m_out << ")";
|
||||
newline();
|
||||
}
|
||||
|
@ -851,7 +721,6 @@ public:
|
|||
m_AUFLIRA("AUFLIRA"),
|
||||
// It's much easier to read those testcases with that.
|
||||
m_no_lets(no_lets),
|
||||
m_is_smt2(is_smt2),
|
||||
m_simplify_implies(simplify_implies)
|
||||
{
|
||||
m_basic_fid = m.get_basic_family_id();
|
||||
|
@ -905,91 +774,59 @@ public:
|
|||
}
|
||||
|
||||
void pp_dt(ast_mark& mark, sort* s) {
|
||||
SASSERT(s->is_sort_of(m_dt_fid, DATATYPE_SORT));
|
||||
datatype_util util(m_manager);
|
||||
ptr_vector<func_decl> const* decls;
|
||||
ptr_vector<sort> rec_sorts;
|
||||
SASSERT(util.is_datatype(s));
|
||||
|
||||
rec_sorts.push_back(s);
|
||||
mark.mark(s, true);
|
||||
sort_ref_vector ps(m_manager);
|
||||
ptr_vector<datatype::def> defs;
|
||||
util.get_defs(s, defs);
|
||||
|
||||
// collect siblings and sorts that have not already been printed.
|
||||
for (unsigned h = 0; h < rec_sorts.size(); ++h) {
|
||||
s = rec_sorts[h];
|
||||
decls = util.get_datatype_constructors(s);
|
||||
|
||||
for (unsigned i = 0; i < decls->size(); ++i) {
|
||||
func_decl* f = (*decls)[i];
|
||||
for (unsigned j = 0; j < f->get_arity(); ++j) {
|
||||
sort* s2 = f->get_domain(j);
|
||||
if (!mark.is_marked(s2)) {
|
||||
if (m_manager.is_uninterp(s2)) {
|
||||
pp_sort_decl(mark, s2);
|
||||
}
|
||||
else if (!util.is_datatype(s2)) {
|
||||
// skip
|
||||
}
|
||||
else if (util.are_siblings(s, s2)) {
|
||||
rec_sorts.push_back(s2);
|
||||
mark.mark(s2, true);
|
||||
}
|
||||
else {
|
||||
pp_sort_decl(mark, s2);
|
||||
}
|
||||
}
|
||||
for (datatype::def* d : defs) {
|
||||
sort_ref sr = d->instantiate(ps);
|
||||
if (mark.is_marked(sr)) return; // already processed
|
||||
mark.mark(sr, true);
|
||||
}
|
||||
|
||||
m_out << "(declare-datatypes (";
|
||||
bool first_def = true;
|
||||
for (datatype::def* d : defs) {
|
||||
if (!first_def) m_out << "\n "; else first_def = false;
|
||||
m_out << "(" << d->name() << " " << d->params().size() << ")";
|
||||
}
|
||||
m_out << ") (";
|
||||
bool first_sort = true;
|
||||
for (datatype::def* d : defs) {
|
||||
if (!first_sort) m_out << "\n "; else first_sort = false;
|
||||
if (!d->params().empty()) {
|
||||
m_out << "(par (";
|
||||
bool first_param = true;
|
||||
for (sort* s : d->params()) {
|
||||
if (!first_param) m_out << " "; else first_param = false;
|
||||
visit_sort(s);
|
||||
}
|
||||
m_out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
if (m_is_smt2) {
|
||||
// TBD: datatypes may be declared parametrically.
|
||||
// get access to parametric generalization, or print
|
||||
// monomorphic specialization with a tag that gets reused at use-point.
|
||||
m_out << "(declare-datatypes () (";
|
||||
}
|
||||
else {
|
||||
m_out << ":datatypes (";
|
||||
}
|
||||
for (unsigned si = 0; si < rec_sorts.size(); ++si) {
|
||||
s = rec_sorts[si];
|
||||
m_out << "(";
|
||||
m_out << m_renaming.get_symbol(s->get_name());
|
||||
m_out << m_renaming.get_symbol(d->name());
|
||||
m_out << " ";
|
||||
decls = util.get_datatype_constructors(s);
|
||||
|
||||
for (unsigned i = 0; i < decls->size(); ++i) {
|
||||
func_decl* f = (*decls)[i];
|
||||
ptr_vector<func_decl> const& accs = *util.get_constructor_accessors(f);
|
||||
if (m_is_smt2 || accs.size() > 0) {
|
||||
m_out << "(";
|
||||
}
|
||||
m_out << m_renaming.get_symbol(f->get_name());
|
||||
if (!accs.empty() || !m_is_smt2) {
|
||||
m_out << " ";
|
||||
}
|
||||
for (unsigned j = 0; j < accs.size(); ++j) {
|
||||
func_decl* a = accs[j];
|
||||
m_out << "(" << m_renaming.get_symbol(a->get_name()) << " ";
|
||||
visit_sort(a->get_range());
|
||||
bool first_constr = true;
|
||||
for (datatype::constructor* f : *d) {
|
||||
if (!first_constr) m_out << " "; else first_constr = false;
|
||||
m_out << "(";
|
||||
m_out << m_renaming.get_symbol(f->name());
|
||||
for (datatype::accessor* a : *f) {
|
||||
m_out << " (" << m_renaming.get_symbol(a->name()) << " ";
|
||||
visit_sort(a->range());
|
||||
m_out << ")";
|
||||
if (j + 1 < accs.size()) m_out << " ";
|
||||
}
|
||||
if (m_is_smt2 || accs.size() > 0) {
|
||||
m_out << ")";
|
||||
if (i + 1 < decls->size()) {
|
||||
m_out << " ";
|
||||
}
|
||||
}
|
||||
m_out << ")";
|
||||
}
|
||||
if (!d->params().empty()) {
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << ")";
|
||||
if (si + 1 < rec_sorts.size()) {
|
||||
m_out << " ";
|
||||
}
|
||||
}
|
||||
if (m_is_smt2) {
|
||||
m_out << ")";
|
||||
}
|
||||
m_out << ")";
|
||||
m_out << "))";
|
||||
newline();
|
||||
}
|
||||
|
||||
|
@ -1002,12 +839,7 @@ public:
|
|||
pp_dt(mark, s);
|
||||
}
|
||||
else {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(declare-sort ";
|
||||
}
|
||||
else {
|
||||
m_out << ":extrasorts (";
|
||||
}
|
||||
m_out << "(declare-sort ";
|
||||
visit_sort(s);
|
||||
m_out << ")";
|
||||
newline();
|
||||
|
@ -1021,29 +853,16 @@ public:
|
|||
}
|
||||
|
||||
void operator()(func_decl* d) {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(declare-fun ";
|
||||
pp_decl(d);
|
||||
m_out << "(";
|
||||
for (unsigned i = 0; i < d->get_arity(); ++i) {
|
||||
if (i > 0) m_out << " ";
|
||||
visit_sort(d->get_domain(i), true);
|
||||
}
|
||||
m_out << ") ";
|
||||
visit_sort(d->get_range());
|
||||
m_out << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "(";
|
||||
pp_decl(d);
|
||||
for (unsigned i = 0; i < d->get_arity(); ++i) {
|
||||
m_out << " ";
|
||||
visit_sort(d->get_domain(i), true);
|
||||
}
|
||||
m_out << " ";
|
||||
visit_sort(d->get_range());
|
||||
m_out << ")";
|
||||
m_out << "(declare-fun ";
|
||||
pp_decl(d);
|
||||
m_out << "(";
|
||||
for (unsigned i = 0; i < d->get_arity(); ++i) {
|
||||
if (i > 0) m_out << " ";
|
||||
visit_sort(d->get_domain(i), true);
|
||||
}
|
||||
m_out << ") ";
|
||||
visit_sort(d->get_range());
|
||||
m_out << ")";
|
||||
}
|
||||
|
||||
void visit_pred(func_decl* d) {
|
||||
|
|
|
@ -19,9 +19,9 @@ Revision History:
|
|||
#ifndef AST_SMT_PP_H_
|
||||
#define AST_SMT_PP_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
#include<string>
|
||||
#include"map.h"
|
||||
#include "util/map.h"
|
||||
|
||||
class smt_renaming {
|
||||
typedef map<symbol, symbol, symbol_hash_proc, symbol_eq_proc> symbol2symbol;
|
||||
|
|
|
@ -22,8 +22,8 @@ Revision History:
|
|||
#ifndef AST_TRAIL_H_
|
||||
#define AST_TRAIL_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"trail.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/trail.h"
|
||||
|
||||
|
||||
template<typename S, typename T>
|
||||
|
|
|
@ -16,13 +16,13 @@ Author:
|
|||
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"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/format.h"
|
||||
#include "ast/ast_translation.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
|
||||
ast_translation::~ast_translation() {
|
||||
reset_cache();
|
||||
|
@ -37,11 +37,9 @@ void ast_translation::cleanup() {
|
|||
}
|
||||
|
||||
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);
|
||||
for (auto & kv : m_cache) {
|
||||
m_from_manager.dec_ref(kv.m_key);
|
||||
m_to_manager.dec_ref(kv.m_value);
|
||||
}
|
||||
m_cache.reset();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ Revision History:
|
|||
#ifndef AST_TRANSLATION_H_
|
||||
#define AST_TRANSLATION_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
class ast_translation {
|
||||
struct frame {
|
||||
|
|
|
@ -16,7 +16,7 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast_util.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
app * mk_list_assoc_app(ast_manager & m, func_decl * f, unsigned num_args, expr * const * args) {
|
||||
SASSERT(f->is_associative());
|
||||
|
|
|
@ -19,8 +19,8 @@ Revision History:
|
|||
#ifndef AST_UTIL_H_
|
||||
#define AST_UTIL_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
|
||||
template<typename C>
|
||||
void remove_duplicates(C & v) {
|
||||
|
|
|
@ -17,11 +17,11 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include<sstream>
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"warning.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "util/warning.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
bv_decl_plugin::bv_decl_plugin():
|
||||
m_bv_sym("bv"),
|
||||
|
@ -784,6 +784,12 @@ bool bv_recognizers::is_numeral(expr const * n, rational & val, unsigned & bv_si
|
|||
return true;
|
||||
}
|
||||
|
||||
bool bv_recognizers::is_numeral(expr const * n, rational & val) const {
|
||||
unsigned bv_size = 0;
|
||||
return is_numeral(n, val, bv_size);
|
||||
}
|
||||
|
||||
|
||||
bool bv_recognizers::is_allone(expr const * e) const {
|
||||
rational r;
|
||||
unsigned bv_size;
|
||||
|
@ -847,7 +853,7 @@ bv_util::bv_util(ast_manager & m):
|
|||
m_plugin = static_cast<bv_decl_plugin*>(m.get_plugin(m.mk_family_id("bv")));
|
||||
}
|
||||
|
||||
app * bv_util::mk_numeral(rational const & val, sort* s) {
|
||||
app * bv_util::mk_numeral(rational const & val, sort* s) const {
|
||||
if (!is_bv_sort(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -855,7 +861,7 @@ app * bv_util::mk_numeral(rational const & val, sort* s) {
|
|||
return mk_numeral(val, bv_size);
|
||||
}
|
||||
|
||||
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) {
|
||||
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
|
||||
parameter p1(val);
|
||||
parameter p[2] = { p1, parameter(static_cast<int>(bv_size)) };
|
||||
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef BV_DECL_PLUGIN_H_
|
||||
#define BV_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
enum bv_sort_kind {
|
||||
BV_SORT
|
||||
|
@ -293,6 +293,7 @@ public:
|
|||
family_id get_fid() const { return m_afid; }
|
||||
family_id get_family_id() const { return get_fid(); }
|
||||
|
||||
bool is_numeral(expr const * n, rational & val) const;
|
||||
bool is_numeral(expr const * n, rational & val, unsigned & bv_size) const;
|
||||
bool is_numeral(expr const * n) const { return is_app_of(n, get_fid(), OP_BV_NUM); }
|
||||
bool is_allone(expr const * e) const;
|
||||
|
@ -381,9 +382,9 @@ public:
|
|||
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
|
||||
app * mk_numeral(rational const & val, sort* s);
|
||||
app * mk_numeral(rational const & val, unsigned bv_size);
|
||||
app * mk_numeral(uint64 u, unsigned bv_size) { return mk_numeral(rational(u, rational::ui64()), bv_size); }
|
||||
app * mk_numeral(rational const & val, sort* s) const;
|
||||
app * mk_numeral(rational const & val, unsigned bv_size) const;
|
||||
app * mk_numeral(uint64 u, unsigned bv_size) const { return mk_numeral(rational(u, rational::ui64()), bv_size); }
|
||||
sort * mk_sort(unsigned bv_size);
|
||||
|
||||
unsigned get_bv_size(sort const * s) const {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
|
@ -11,49 +11,390 @@ Abstract:
|
|||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-09.
|
||||
Nikolaj Bjorner (nbjorner) 2017-9-1
|
||||
|
||||
Revision History:
|
||||
|
||||
rewritten to support SMTLIB-2.6 parameters from
|
||||
Leonardo de Moura (leonardo) 2008-01-09.
|
||||
|
||||
--*/
|
||||
#ifndef DATATYPE_DECL_PLUGIN_H_
|
||||
#define DATATYPE_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"tptr.h"
|
||||
#include"buffer.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/buffer.h"
|
||||
#include "util/symbol_table.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
|
||||
enum datatype_sort_kind {
|
||||
|
||||
enum sort_kind {
|
||||
DATATYPE_SORT
|
||||
};
|
||||
|
||||
enum datatype_op_kind {
|
||||
enum op_kind {
|
||||
OP_DT_CONSTRUCTOR,
|
||||
OP_DT_RECOGNISER,
|
||||
OP_DT_ACCESSOR,
|
||||
OP_DT_IS,
|
||||
OP_DT_ACCESSOR,
|
||||
OP_DT_UPDATE_FIELD,
|
||||
LAST_DT_OP
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Auxiliary class used to declare inductive datatypes.
|
||||
It may be a sort or an integer. If it is an integer,
|
||||
then it represents a reference to a recursive type.
|
||||
namespace datatype {
|
||||
|
||||
For example, consider the datatypes
|
||||
Datatype
|
||||
Tree = tree(value:Real, children:TreeList)
|
||||
TreeList = cons_t(first_t:Tree, rest_t:Tree)
|
||||
| nil_t
|
||||
End
|
||||
|
||||
The recursive occurrences of Tree and TreeList will have idx 0 and
|
||||
1 respectively.
|
||||
class util;
|
||||
class def;
|
||||
class accessor;
|
||||
class constructor;
|
||||
|
||||
|
||||
class accessor {
|
||||
symbol m_name;
|
||||
sort_ref m_range;
|
||||
unsigned m_index; // reference to recursive data-type may only get resolved after all mutually recursive data-types are procssed.
|
||||
constructor* m_constructor;
|
||||
public:
|
||||
accessor(ast_manager& m, symbol const& n, sort* range):
|
||||
m_name(n),
|
||||
m_range(range, m),
|
||||
m_index(UINT_MAX)
|
||||
{}
|
||||
accessor(ast_manager& m, symbol const& n, unsigned index):
|
||||
m_name(n),
|
||||
m_range(m),
|
||||
m_index(index)
|
||||
{}
|
||||
sort* range() const { return m_range; }
|
||||
void fix_range(sort_ref_vector const& dts);
|
||||
symbol const& name() const { return m_name; }
|
||||
func_decl_ref instantiate(sort_ref_vector const& ps) const;
|
||||
func_decl_ref instantiate(sort* dt) const;
|
||||
void attach(constructor* d) { m_constructor = d; }
|
||||
constructor const& get_constructor() const { return *m_constructor; }
|
||||
def const& get_def() const;
|
||||
util& u() const;
|
||||
accessor* translate(ast_translation& tr);
|
||||
};
|
||||
|
||||
class constructor {
|
||||
symbol m_name;
|
||||
symbol m_recognizer;
|
||||
ptr_vector<accessor> m_accessors;
|
||||
def* m_def;
|
||||
public:
|
||||
constructor(symbol n, symbol const& r): m_name(n), m_recognizer(r) {}
|
||||
~constructor();
|
||||
void add(accessor* a) { m_accessors.push_back(a); a->attach(this); }
|
||||
symbol const& name() const { return m_name; }
|
||||
symbol const& recognizer() const { return m_recognizer; }
|
||||
ptr_vector<accessor> const& accessors() const { return m_accessors; }
|
||||
ptr_vector<accessor>::const_iterator begin() const { return m_accessors.begin(); }
|
||||
ptr_vector<accessor>::const_iterator end() const { return m_accessors.end(); }
|
||||
ptr_vector<accessor>::iterator begin() { return m_accessors.begin(); }
|
||||
ptr_vector<accessor>::iterator end() { return m_accessors.end(); }
|
||||
func_decl_ref instantiate(sort_ref_vector const& ps) const;
|
||||
func_decl_ref instantiate(sort* dt) const;
|
||||
void attach(def* d) { m_def = d; }
|
||||
def const& get_def() const { return *m_def; }
|
||||
util& u() const;
|
||||
constructor* translate(ast_translation& tr);
|
||||
};
|
||||
|
||||
namespace param_size {
|
||||
class size {
|
||||
unsigned m_ref;
|
||||
public:
|
||||
size(): m_ref(0) {}
|
||||
virtual ~size() {}
|
||||
void inc_ref() { ++m_ref; }
|
||||
void dec_ref() { --m_ref; if (m_ref == 0) dealloc(this); }
|
||||
static size* mk_offset(sort_size const& s);
|
||||
static size* mk_param(sort_ref& p);
|
||||
static size* mk_plus(size* a1, size* a2);
|
||||
static size* mk_times(size* a1, size* a2);
|
||||
static size* mk_plus(ptr_vector<size>& szs);
|
||||
static size* mk_times(ptr_vector<size>& szs);
|
||||
static size* mk_power(size* a1, size* a2);
|
||||
|
||||
virtual size* subst(obj_map<sort, size*>& S) = 0;
|
||||
virtual sort_size eval(obj_map<sort, sort_size> const& S) = 0;
|
||||
|
||||
};
|
||||
struct offset : public size {
|
||||
sort_size m_offset;
|
||||
offset(sort_size const& s): m_offset(s) {}
|
||||
virtual ~offset() {}
|
||||
virtual size* subst(obj_map<sort,size*>& S) { return this; }
|
||||
virtual sort_size eval(obj_map<sort, sort_size> const& S) { return m_offset; }
|
||||
};
|
||||
struct plus : public size {
|
||||
size* m_arg1, *m_arg2;
|
||||
plus(size* a1, size* a2): m_arg1(a1), m_arg2(a2) { a1->inc_ref(); a2->inc_ref();}
|
||||
virtual ~plus() { m_arg1->dec_ref(); m_arg2->dec_ref(); }
|
||||
virtual size* subst(obj_map<sort,size*>& S) { return mk_plus(m_arg1->subst(S), m_arg2->subst(S)); }
|
||||
virtual sort_size eval(obj_map<sort, sort_size> const& S) {
|
||||
sort_size s1 = m_arg1->eval(S);
|
||||
sort_size s2 = m_arg2->eval(S);
|
||||
if (s1.is_infinite()) return s1;
|
||||
if (s2.is_infinite()) return s2;
|
||||
if (s1.is_very_big()) return s1;
|
||||
if (s2.is_very_big()) return s2;
|
||||
rational r = rational(s1.size(), rational::ui64()) + rational(s2.size(), rational::ui64());
|
||||
return sort_size(r);
|
||||
}
|
||||
};
|
||||
struct times : public size {
|
||||
size* m_arg1, *m_arg2;
|
||||
times(size* a1, size* a2): m_arg1(a1), m_arg2(a2) { a1->inc_ref(); a2->inc_ref(); }
|
||||
virtual ~times() { m_arg1->dec_ref(); m_arg2->dec_ref(); }
|
||||
virtual size* subst(obj_map<sort,size*>& S) { return mk_times(m_arg1->subst(S), m_arg2->subst(S)); }
|
||||
virtual sort_size eval(obj_map<sort, sort_size> const& S) {
|
||||
sort_size s1 = m_arg1->eval(S);
|
||||
sort_size s2 = m_arg2->eval(S);
|
||||
if (s1.is_infinite()) return s1;
|
||||
if (s2.is_infinite()) return s2;
|
||||
if (s1.is_very_big()) return s1;
|
||||
if (s2.is_very_big()) return s2;
|
||||
rational r = rational(s1.size(), rational::ui64()) * rational(s2.size(), rational::ui64());
|
||||
return sort_size(r);
|
||||
}
|
||||
};
|
||||
struct power : public size {
|
||||
size* m_arg1, *m_arg2;
|
||||
power(size* a1, size* a2): m_arg1(a1), m_arg2(a2) { a1->inc_ref(); a2->inc_ref(); }
|
||||
virtual ~power() { m_arg1->dec_ref(); m_arg2->dec_ref(); }
|
||||
virtual size* subst(obj_map<sort,size*>& S) { return mk_power(m_arg1->subst(S), m_arg2->subst(S)); }
|
||||
virtual sort_size eval(obj_map<sort, sort_size> const& S) {
|
||||
sort_size s1 = m_arg1->eval(S);
|
||||
sort_size s2 = m_arg2->eval(S);
|
||||
// s1^s2
|
||||
if (s1.is_infinite()) return s1;
|
||||
if (s2.is_infinite()) return s2;
|
||||
if (s1.is_very_big()) return s1;
|
||||
if (s2.is_very_big()) return s2;
|
||||
if (s1.size() == 1) return s1;
|
||||
if (s2.size() == 1) return s1;
|
||||
if (s1.size() > (2 << 20) || s2.size() > 10) return sort_size::mk_very_big();
|
||||
rational r = ::power(rational(s1.size(), rational::ui64()), static_cast<unsigned>(s2.size()));
|
||||
return sort_size(r);
|
||||
}
|
||||
};
|
||||
struct sparam : public size {
|
||||
sort_ref m_param;
|
||||
sparam(sort_ref& p): m_param(p) {}
|
||||
virtual ~sparam() {}
|
||||
virtual size* subst(obj_map<sort,size*>& S) { return S[m_param]; }
|
||||
virtual sort_size eval(obj_map<sort, sort_size> const& S) { return S[m_param]; }
|
||||
};
|
||||
};
|
||||
|
||||
class def {
|
||||
ast_manager& m;
|
||||
util& m_util;
|
||||
symbol m_name;
|
||||
unsigned m_class_id;
|
||||
param_size::size* m_sort_size;
|
||||
sort_ref_vector m_params;
|
||||
mutable sort_ref m_sort;
|
||||
ptr_vector<constructor> m_constructors;
|
||||
public:
|
||||
def(ast_manager& m, util& u, symbol const& n, unsigned class_id, unsigned num_params, sort * const* params):
|
||||
m(m),
|
||||
m_util(u),
|
||||
m_name(n),
|
||||
m_class_id(class_id),
|
||||
m_sort_size(0),
|
||||
m_params(m, num_params, params),
|
||||
m_sort(m)
|
||||
{}
|
||||
~def() {
|
||||
if (m_sort_size) m_sort_size->dec_ref();
|
||||
for (constructor* c : m_constructors) dealloc(c);
|
||||
m_constructors.reset();
|
||||
}
|
||||
void add(constructor* c) {
|
||||
m_constructors.push_back(c);
|
||||
c->attach(this);
|
||||
}
|
||||
symbol const& name() const { return m_name; }
|
||||
unsigned id() const { return m_class_id; }
|
||||
sort_ref instantiate(sort_ref_vector const& ps) const;
|
||||
ptr_vector<constructor> const& constructors() const { return m_constructors; }
|
||||
ptr_vector<constructor>::const_iterator begin() const { return m_constructors.begin(); }
|
||||
ptr_vector<constructor>::const_iterator end() const { return m_constructors.end(); }
|
||||
ptr_vector<constructor>::iterator begin() { return m_constructors.begin(); }
|
||||
ptr_vector<constructor>::iterator end() { return m_constructors.end(); }
|
||||
sort_ref_vector const& params() const { return m_params; }
|
||||
util& u() const { return m_util; }
|
||||
param_size::size* sort_size() { return m_sort_size; }
|
||||
void set_sort_size(param_size::size* p) { m_sort_size = p; p->inc_ref(); m_sort = 0; }
|
||||
def* translate(ast_translation& tr, util& u);
|
||||
};
|
||||
|
||||
namespace decl {
|
||||
|
||||
class plugin : public decl_plugin {
|
||||
mutable scoped_ptr<util> m_util;
|
||||
map<symbol, def*, symbol_hash_proc, symbol_eq_proc> m_defs;
|
||||
svector<symbol> m_def_block;
|
||||
unsigned m_class_id;
|
||||
util & u() const;
|
||||
|
||||
virtual void inherit(decl_plugin* other_p, ast_translation& tr);
|
||||
|
||||
public:
|
||||
plugin(): m_class_id(0) {}
|
||||
virtual ~plugin();
|
||||
|
||||
virtual void finalize();
|
||||
|
||||
virtual decl_plugin * mk_fresh() { return alloc(plugin); }
|
||||
|
||||
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
|
||||
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool is_fully_interp(sort * s) const;
|
||||
|
||||
virtual bool is_value(app* e) const;
|
||||
|
||||
virtual bool is_unique_value(app * e) const { return is_value(e); }
|
||||
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
|
||||
void begin_def_block() { m_class_id++; m_def_block.reset(); }
|
||||
|
||||
void end_def_block();
|
||||
|
||||
def* mk(symbol const& name, unsigned n, sort * const * params);
|
||||
|
||||
void remove(symbol const& d);
|
||||
|
||||
bool mk_datatypes(unsigned num_datatypes, def * const * datatypes, unsigned num_params, sort* const* sort_params, sort_ref_vector & new_sorts);
|
||||
|
||||
def const& get_def(sort* s) const { return *(m_defs[datatype_name(s)]); }
|
||||
def& get_def(symbol const& s) { return *(m_defs[s]); }
|
||||
bool is_declared(sort* s) const { return m_defs.contains(datatype_name(s)); }
|
||||
private:
|
||||
bool is_value_visit(expr * arg, ptr_buffer<app> & todo) const;
|
||||
|
||||
func_decl * mk_update_field(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
func_decl * mk_constructor(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
func_decl * mk_accessor(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
func_decl * mk_recognizer(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
func_decl * mk_is(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
symbol datatype_name(sort * s) const {
|
||||
//SASSERT(u().is_datatype(s));
|
||||
return s->get_parameter(0).get_symbol();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class util {
|
||||
ast_manager & m;
|
||||
family_id m_family_id;
|
||||
mutable decl::plugin* m_plugin;
|
||||
|
||||
|
||||
obj_map<sort, ptr_vector<func_decl> *> m_datatype2constructors;
|
||||
obj_map<sort, func_decl *> m_datatype2nonrec_constructor;
|
||||
obj_map<func_decl, ptr_vector<func_decl> *> m_constructor2accessors;
|
||||
obj_map<func_decl, func_decl *> m_constructor2recognizer;
|
||||
obj_map<func_decl, func_decl *> m_recognizer2constructor;
|
||||
obj_map<func_decl, func_decl *> m_accessor2constructor;
|
||||
obj_map<sort, bool> m_is_recursive;
|
||||
obj_map<sort, bool> m_is_enum;
|
||||
mutable obj_map<sort, bool> m_is_fully_interp;
|
||||
mutable ast_ref_vector m_asts;
|
||||
ptr_vector<ptr_vector<func_decl> > m_vectors;
|
||||
unsigned m_start;
|
||||
mutable ptr_vector<sort> m_fully_interp_trail;
|
||||
|
||||
func_decl * get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set);
|
||||
|
||||
friend class decl::plugin;
|
||||
|
||||
bool is_recursive_core(sort * s) const;
|
||||
sort_size get_datatype_size(sort* s0);
|
||||
void compute_datatype_size_functions(svector<symbol> const& names);
|
||||
param_size::size* get_sort_size(sort_ref_vector const& params, sort* s);
|
||||
bool is_well_founded(unsigned num_types, sort* const* sorts);
|
||||
def& get_def(symbol const& s) { return m_plugin->get_def(s); }
|
||||
void get_subsorts(sort* s, ptr_vector<sort>& sorts) const;
|
||||
|
||||
public:
|
||||
util(ast_manager & m);
|
||||
~util();
|
||||
ast_manager & get_manager() const { return m; }
|
||||
// sort * mk_datatype_sort(symbol const& name, unsigned n, sort* const* params);
|
||||
bool is_datatype(sort const* s) const { return is_sort_of(s, m_family_id, DATATYPE_SORT); }
|
||||
bool is_enum_sort(sort* s);
|
||||
bool is_recursive(sort * ty);
|
||||
bool is_constructor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer(func_decl * f) const { return is_recognizer0(f) || is_is(f); }
|
||||
bool is_recognizer0(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_RECOGNISER); }
|
||||
bool is_is(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_IS); }
|
||||
bool is_accessor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_ACCESSOR); }
|
||||
bool is_update_field(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_UPDATE_FIELD); }
|
||||
bool is_constructor(app * f) const { return is_app_of(f, m_family_id, OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer0(app * f) const { return is_app_of(f, m_family_id, OP_DT_RECOGNISER);}
|
||||
bool is_is(app * f) const { return is_app_of(f, m_family_id, OP_DT_IS);}
|
||||
bool is_recognizer(app * f) const { return is_recognizer0(f) || is_is(f); }
|
||||
bool is_accessor(app * f) const { return is_app_of(f, m_family_id, OP_DT_ACCESSOR); }
|
||||
bool is_update_field(app * f) const { return is_app_of(f, m_family_id, OP_DT_UPDATE_FIELD); }
|
||||
ptr_vector<func_decl> const * get_datatype_constructors(sort * ty);
|
||||
unsigned get_datatype_num_constructors(sort * ty);
|
||||
unsigned get_datatype_num_parameter_sorts(sort * ty);
|
||||
sort* get_datatype_parameter_sort(sort * ty, unsigned idx);
|
||||
func_decl * get_non_rec_constructor(sort * ty);
|
||||
func_decl * get_constructor_recognizer(func_decl * constructor);
|
||||
ptr_vector<func_decl> const * get_constructor_accessors(func_decl * constructor);
|
||||
func_decl * get_accessor_constructor(func_decl * accessor);
|
||||
func_decl * get_recognizer_constructor(func_decl * recognizer) const;
|
||||
family_id get_family_id() const { return m_family_id; }
|
||||
bool are_siblings(sort * s1, sort * s2);
|
||||
bool is_func_decl(op_kind k, unsigned num_params, parameter const* params, func_decl* f);
|
||||
bool is_constructor_of(unsigned num_params, parameter const* params, func_decl* f);
|
||||
void reset();
|
||||
bool is_declared(sort* s) const;
|
||||
void display_datatype(sort *s, std::ostream& strm);
|
||||
bool is_fully_interp(sort * s) const;
|
||||
sort_ref_vector datatype_params(sort * s) const;
|
||||
unsigned get_constructor_idx(func_decl * f) const;
|
||||
unsigned get_recognizer_constructor_idx(func_decl * f) const;
|
||||
decl::plugin* get_plugin() { return m_plugin; }
|
||||
void get_defs(sort* s, ptr_vector<def>& defs);
|
||||
def const& get_def(sort* s) const;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
typedef datatype::accessor accessor_decl;
|
||||
typedef datatype::constructor constructor_decl;
|
||||
typedef datatype::def datatype_decl;
|
||||
typedef datatype::decl::plugin datatype_decl_plugin;
|
||||
typedef datatype::util datatype_util;
|
||||
|
||||
This is a transient value, it is only used to declare a set of
|
||||
recursive datatypes.
|
||||
*/
|
||||
class type_ref {
|
||||
void * m_data;
|
||||
public:
|
||||
|
@ -67,181 +408,29 @@ public:
|
|||
int get_idx() const { return UNBOXINT(m_data); }
|
||||
};
|
||||
|
||||
class accessor_decl;
|
||||
class constructor_decl;
|
||||
class datatype_decl;
|
||||
class datatype_util;
|
||||
inline accessor_decl * mk_accessor_decl(ast_manager& m, symbol const & n, type_ref const & t) {
|
||||
if (t.is_idx()) {
|
||||
return alloc(accessor_decl, m, n, t.get_idx());
|
||||
}
|
||||
else {
|
||||
return alloc(accessor_decl, m, n, t.get_sort());
|
||||
}
|
||||
}
|
||||
|
||||
inline constructor_decl * mk_constructor_decl(symbol const & n, symbol const & r, unsigned num_accessors, accessor_decl * * acs) {
|
||||
constructor_decl* c = alloc(constructor_decl, n, r);
|
||||
for (unsigned i = 0; i < num_accessors; ++i) {
|
||||
c->add(acs[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
accessor_decl * mk_accessor_decl(symbol const & n, type_ref const & t);
|
||||
void del_accessor_decl(accessor_decl * d);
|
||||
void del_accessor_decls(unsigned num, accessor_decl * const * as);
|
||||
// Remark: the constructor becomes the owner of the accessor_decls
|
||||
constructor_decl * mk_constructor_decl(symbol const & n, symbol const & r, unsigned num_accessors, accessor_decl * const * acs);
|
||||
void del_constructor_decl(constructor_decl * d);
|
||||
void del_constructor_decls(unsigned num, constructor_decl * const * cs);
|
||||
// Remark: the datatype becomes the owner of the constructor_decls
|
||||
datatype_decl * mk_datatype_decl(symbol const & n, unsigned num_constructors, constructor_decl * const * cs);
|
||||
void del_datatype_decl(datatype_decl * d);
|
||||
void del_datatype_decls(unsigned num, datatype_decl * const * ds);
|
||||
datatype_decl * mk_datatype_decl(datatype_util& u, symbol const & n, unsigned num_params, sort*const* params, unsigned num_constructors, constructor_decl * const * cs);
|
||||
inline void del_datatype_decl(datatype_decl * d) {}
|
||||
inline void del_datatype_decls(unsigned num, datatype_decl * const * ds) {}
|
||||
|
||||
class datatype_decl_plugin : public decl_plugin {
|
||||
mutable scoped_ptr<datatype_util> m_util;
|
||||
datatype_util & get_util() const;
|
||||
public:
|
||||
datatype_decl_plugin() {}
|
||||
|
||||
virtual ~datatype_decl_plugin();
|
||||
virtual void finalize();
|
||||
|
||||
virtual decl_plugin * mk_fresh() { return alloc(datatype_decl_plugin); }
|
||||
|
||||
|
||||
/**
|
||||
Contract for sort:
|
||||
parameters[0] - (int) n - number of recursive types.
|
||||
parameters[1] - (int) i - index 0..n-1 of which type is defined.
|
||||
|
||||
parameters[2] - (int) p - number of type parameters.
|
||||
|
||||
for j = 0..p-1
|
||||
parameters[3 + j] - (sort) s - type parameter
|
||||
|
||||
c_offset := 3 + p
|
||||
for j in 0..n-1
|
||||
parameters[c_offset + 2*j] - (symbol) name of the type
|
||||
parameters[c_offset + 2*j + 1] - (int) o - offset where the constructors are defined.
|
||||
|
||||
for each offset o at parameters[2 + 2*j + 1] for some j in 0..n-1
|
||||
parameters[o] - (int) m - number of constructors
|
||||
parameters[o+1] - (int) k_1 - offset for constructor definition
|
||||
...
|
||||
parameters[o+m] - (int) k_m - offset for constructor definition
|
||||
|
||||
for each offset k_i at parameters[o+s] for some s in 0..m-1
|
||||
parameters[k_i] - (symbol) name of the constructor
|
||||
parameters[k_i+1] - (symbol) name of the recognizer
|
||||
parameters[k_i+2] - (int) m' - number of accessors
|
||||
parameters[k_i+3+2*r] - (symbol) name of the r accessor
|
||||
parameters[k_i+3+2*r+1] - (int or type_ast) type of the accessor. If integer, then the value must be in [0..n-1], and it
|
||||
represents an reference to the recursive type.
|
||||
|
||||
The idea with the additional offsets is that
|
||||
access to relevant constructors and types can be performed using
|
||||
a few address calculations.
|
||||
*/
|
||||
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
|
||||
|
||||
/**
|
||||
Contract for constructors
|
||||
parameters[0] - (ast) datatype ast.
|
||||
parmaeters[1] - (int) constructor idx.
|
||||
Contract for accessors
|
||||
parameters[0] - (ast) datatype ast.
|
||||
parameters[1] - (int) constructor idx.
|
||||
parameters[2] - (int) accessor idx.
|
||||
Contract for tester
|
||||
parameters[0] - (ast) datatype ast.
|
||||
parameters[1] - (int) constructor idx.
|
||||
*/
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
bool mk_datatypes(unsigned num_datatypes, datatype_decl * const * datatypes, unsigned num_params, sort* const* sort_params, sort_ref_vector & new_sorts);
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool is_fully_interp(sort const * s) const;
|
||||
|
||||
virtual bool is_value(app* e) const;
|
||||
|
||||
virtual bool is_unique_value(app * e) const { return is_value(e); }
|
||||
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
|
||||
static unsigned constructor_offset(sort const* s);
|
||||
static unsigned constructor_offset(parameter const& p);
|
||||
static unsigned constructor_offset(parameter const* ps);
|
||||
|
||||
static unsigned constructor_offset(sort const* s, unsigned tid);
|
||||
static unsigned constructor_offset(parameter const* ps, unsigned tid);
|
||||
|
||||
private:
|
||||
bool is_value_visit(expr * arg, ptr_buffer<app> & todo) const;
|
||||
|
||||
func_decl * mk_update_field(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
};
|
||||
|
||||
class datatype_util {
|
||||
ast_manager & m_manager;
|
||||
family_id m_family_id;
|
||||
|
||||
func_decl * get_constructor(sort * ty, unsigned c_id) const;
|
||||
|
||||
obj_map<sort, ptr_vector<func_decl> *> m_datatype2constructors;
|
||||
obj_map<sort, func_decl *> m_datatype2nonrec_constructor;
|
||||
obj_map<func_decl, ptr_vector<func_decl> *> m_constructor2accessors;
|
||||
obj_map<func_decl, func_decl *> m_constructor2recognizer;
|
||||
obj_map<func_decl, func_decl *> m_recognizer2constructor;
|
||||
obj_map<func_decl, func_decl *> m_accessor2constructor;
|
||||
obj_map<sort, bool> m_is_recursive;
|
||||
obj_map<sort, bool> m_is_enum;
|
||||
ast_ref_vector m_asts;
|
||||
ptr_vector<ptr_vector<func_decl> > m_vectors;
|
||||
unsigned m_start;
|
||||
|
||||
func_decl * get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set);
|
||||
func_decl * get_constructor(sort * ty, unsigned c_id);
|
||||
|
||||
public:
|
||||
datatype_util(ast_manager & m);
|
||||
~datatype_util();
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
bool is_datatype(sort * s) const { return is_sort_of(s, m_family_id, DATATYPE_SORT); }
|
||||
bool is_enum_sort(sort* s);
|
||||
|
||||
bool is_recursive(sort * ty);
|
||||
bool is_constructor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_RECOGNISER); }
|
||||
bool is_accessor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_ACCESSOR); }
|
||||
bool is_update_field(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_UPDATE_FIELD); }
|
||||
bool is_constructor(app * f) const { return is_app_of(f, m_family_id, OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer(app * f) const { return is_app_of(f, m_family_id, OP_DT_RECOGNISER); }
|
||||
bool is_accessor(app * f) const { return is_app_of(f, m_family_id, OP_DT_ACCESSOR); }
|
||||
bool is_update_field(app * f) const { return is_app_of(f, m_family_id, OP_DT_UPDATE_FIELD); }
|
||||
ptr_vector<func_decl> const * get_datatype_constructors(sort * ty);
|
||||
unsigned get_datatype_num_constructors(sort * ty) {
|
||||
SASSERT(is_datatype(ty));
|
||||
unsigned tid = ty->get_parameter(1).get_int();
|
||||
unsigned o = datatype_decl_plugin::constructor_offset(ty, tid);
|
||||
return ty->get_parameter(o).get_int();
|
||||
}
|
||||
unsigned get_datatype_num_parameter_sorts(sort * ty) {
|
||||
SASSERT(is_datatype(ty));
|
||||
return ty->get_parameter(2).get_int();
|
||||
}
|
||||
sort* get_datatype_parameter_sort(sort * ty, unsigned idx) {
|
||||
SASSERT(is_datatype(ty));
|
||||
SASSERT(idx < get_datatype_num_parameter_sorts(ty));
|
||||
return to_sort(ty->get_parameter(3 + idx).get_ast());
|
||||
}
|
||||
unsigned get_constructor_idx(func_decl * f) const { SASSERT(is_constructor(f)); return f->get_parameter(1).get_int(); }
|
||||
unsigned get_recognizer_constructor_idx(func_decl * f) const { SASSERT(is_recognizer(f)); return f->get_parameter(1).get_int(); }
|
||||
func_decl * get_non_rec_constructor(sort * ty);
|
||||
func_decl * get_constructor_recognizer(func_decl * constructor);
|
||||
ptr_vector<func_decl> const * get_constructor_accessors(func_decl * constructor);
|
||||
func_decl * get_accessor_constructor(func_decl * accessor);
|
||||
func_decl * get_recognizer_constructor(func_decl * recognizer);
|
||||
family_id get_family_id() const { return m_family_id; }
|
||||
bool are_siblings(sort * s1, sort * s2);
|
||||
bool is_func_decl(datatype_op_kind k, unsigned num_params, parameter const* params, func_decl* f);
|
||||
bool is_constructor_of(unsigned num_params, parameter const* params, func_decl* f);
|
||||
void reset();
|
||||
void display_datatype(sort *s, std::ostream& strm);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* DATATYPE_DECL_PLUGIN_H_ */
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"decl_collector.h"
|
||||
#include "ast/decl_collector.h"
|
||||
|
||||
void decl_collector::visit_sort(sort * n) {
|
||||
family_id fid = n->get_family_id();
|
||||
|
|
|
@ -20,8 +20,8 @@ Revision History:
|
|||
#ifndef SMT_DECL_COLLECTOR_H_
|
||||
#define SMT_DECL_COLLECTOR_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
|
||||
class decl_collector {
|
||||
ast_manager & m_manager;
|
||||
|
|
|
@ -18,12 +18,12 @@ Revision History:
|
|||
--*/
|
||||
#include<sstream>
|
||||
|
||||
#include "ast_pp.h"
|
||||
#include "array_decl_plugin.h"
|
||||
#include "datatype_decl_plugin.h"
|
||||
#include "dl_decl_plugin.h"
|
||||
#include "warning.h"
|
||||
#include "reg_decl_plugins.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/dl_decl_plugin.h"
|
||||
#include "util/warning.h"
|
||||
#include "ast/reg_decl_plugins.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ Revision History:
|
|||
#ifndef DL_DECL_PLUGIN_H_
|
||||
#define DL_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "arith_decl_plugin.h"
|
||||
#include "bv_decl_plugin.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
|
|
@ -17,13 +17,13 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"expr2polynomial.h"
|
||||
#include"expr2var.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"z3_exception.h"
|
||||
#include"cooperate.h"
|
||||
#include"common_msgs.h"
|
||||
#include "ast/expr2polynomial.h"
|
||||
#include "ast/expr2var.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/z3_exception.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "util/common_msgs.h"
|
||||
|
||||
struct expr2polynomial::imp {
|
||||
struct frame {
|
||||
|
|
|
@ -20,8 +20,8 @@ Notes:
|
|||
#ifndef EXPR2POLYNOMIAL_H_
|
||||
#define EXPR2POLYNOMIAL_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"polynomial.h"
|
||||
#include "ast/ast.h"
|
||||
#include "math/polynomial/polynomial.h"
|
||||
|
||||
class expr2var;
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"expr2var.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ref_util.h"
|
||||
#include "ast/expr2var.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/ref_util.h"
|
||||
|
||||
void expr2var::insert(expr * n, var v) {
|
||||
if (!is_uninterp_const(n)) {
|
||||
|
|
|
@ -23,8 +23,8 @@ Notes:
|
|||
#ifndef EXPR2VAR_H_
|
||||
#define EXPR2VAR_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
|
||||
/**
|
||||
\brief The mapping between Z3 expressions and (low level) variables.
|
||||
|
|
|
@ -17,8 +17,8 @@ Notes:
|
|||
|
||||
--*/
|
||||
|
||||
#include "expr_abstract.h"
|
||||
#include "map.h"
|
||||
#include "ast/expr_abstract.h"
|
||||
#include "util/map.h"
|
||||
|
||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ Notes:
|
|||
#ifndef EXPR_ABSTRACT_H_
|
||||
#define EXPR_ABSTRACT_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
class expr_abstractor {
|
||||
ast_manager& m;
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include "expr_functors.h"
|
||||
#include "ast/expr_functors.h"
|
||||
|
||||
// ----------
|
||||
// check_pred
|
||||
|
|
|
@ -22,8 +22,8 @@ Revision History:
|
|||
#ifndef EXPR_FUNCTORS_H_
|
||||
#define EXPR_FUNCTORS_H_
|
||||
|
||||
#include "ast.h"
|
||||
#include "expr_map.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/expr_map.h"
|
||||
|
||||
class i_expr_pred {
|
||||
public:
|
||||
|
|
|
@ -18,8 +18,8 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"expr_map.h"
|
||||
#include"dec_ref_util.h"
|
||||
#include "ast/expr_map.h"
|
||||
#include "util/dec_ref_util.h"
|
||||
|
||||
expr_map::expr_map(ast_manager & m):
|
||||
m_manager(m),
|
||||
|
|
|
@ -21,8 +21,8 @@ Notes:
|
|||
#ifndef EXPR_MAP_H_
|
||||
#define EXPR_MAP_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
|
||||
/**
|
||||
\brief Map from expressions to expressions+proofs.
|
||||
|
|
|
@ -19,8 +19,8 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"for_each_expr.h"
|
||||
#include"expr_stat.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/expr_stat.h"
|
||||
|
||||
void get_expr_stat(expr * n, expr_stat & r) {
|
||||
typedef std::pair<expr *, unsigned> pair;
|
||||
|
|
|
@ -16,8 +16,8 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"expr_substitution.h"
|
||||
#include"ref_util.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "util/ref_util.h"
|
||||
|
||||
typedef obj_map<expr, proof*> expr2proof;
|
||||
typedef obj_map<expr, expr_dependency*> expr2expr_dependency;
|
||||
|
|
|
@ -19,7 +19,7 @@ Notes:
|
|||
#ifndef EXPR_SUBSTITUTION_H_
|
||||
#define EXPR_SUBSTITUTION_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
class expr_substitution {
|
||||
ast_manager & m_manager;
|
||||
|
@ -52,4 +52,38 @@ public:
|
|||
void cleanup();
|
||||
};
|
||||
|
||||
class scoped_expr_substitution {
|
||||
expr_substitution& m_subst;
|
||||
expr_ref_vector m_trail;
|
||||
unsigned_vector m_trail_lim;
|
||||
public:
|
||||
|
||||
scoped_expr_substitution(expr_substitution& s): m_subst(s), m_trail(s.m()) {}
|
||||
~scoped_expr_substitution() {}
|
||||
|
||||
void insert(expr * s, expr * def, proof * def_pr = 0, expr_dependency * def_dep = 0) {
|
||||
if (!m_subst.contains(s)) {
|
||||
m_subst.insert(s, def, def_pr, def_dep);
|
||||
m_trail.push_back(s);
|
||||
}
|
||||
}
|
||||
void reset() { m_subst.reset(); m_trail.reset(); m_trail_lim.reset(); }
|
||||
void push() { m_trail_lim.push_back(m_trail.size()); }
|
||||
void pop(unsigned n) {
|
||||
if (n > 0) {
|
||||
unsigned new_sz = m_trail_lim.size() - n;
|
||||
unsigned old_sz = m_trail_lim[new_sz];
|
||||
for (unsigned i = old_sz; i < m_trail.size(); ++i) m_subst.erase(m_trail[i].get());
|
||||
m_trail.resize(old_sz);
|
||||
m_trail_lim.resize(new_sz);
|
||||
}
|
||||
}
|
||||
bool empty() const { return m_subst.empty(); }
|
||||
expr* find(expr * e) { proof* pr; expr* d = 0; if (find(e, d, pr)) return d; else return e; }
|
||||
bool find(expr * s, expr * & def, proof * & def_pr) { return m_subst.find(s, def, def_pr); }
|
||||
bool find(expr * s, expr * & def, proof * & def_pr, expr_dependency * & def_dep) { return m_subst.find(s, def, def_pr, def_dep); }
|
||||
bool contains(expr * s) { return m_subst.contains(s); }
|
||||
void cleanup() { m_subst.cleanup(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
109
src/ast/factor_equivs.cpp
Normal file
109
src/ast/factor_equivs.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Arie Gurfinkel
|
||||
|
||||
Module Name:
|
||||
|
||||
factor_equivs.cpp
|
||||
|
||||
Abstract:
|
||||
Factor equivalence classes out of an expression.
|
||||
|
||||
"Equivalence class structure" for objs. Uses a union_find structure internally.
|
||||
Operations are :
|
||||
-Declare a new equivalence class with a single element
|
||||
-Merge two equivalence classes
|
||||
-Retrieve whether two elements are in the same equivalence class
|
||||
-Iterate on all the elements of the equivalence class of a given element
|
||||
-Iterate on all equivalence classes (and then within them)
|
||||
|
||||
Author:
|
||||
|
||||
Julien Braine
|
||||
Arie Gurfinkel
|
||||
|
||||
Revision History:
|
||||
|
||||
*/
|
||||
|
||||
#include "ast/factor_equivs.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
|
||||
/**
|
||||
Factors input vector v into equivalence classes and the rest
|
||||
*/
|
||||
void factor_eqs(expr_ref_vector &v, expr_equiv_class &equiv) {
|
||||
ast_manager &m = v.get_manager();
|
||||
arith_util arith(m);
|
||||
expr *e1 = 0, *e2 = 0;
|
||||
|
||||
flatten_and(v);
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
if (m.is_eq(v.get(i), e1, e2)) {
|
||||
if (arith.is_zero(e1)) {
|
||||
std::swap(e1, e2);
|
||||
}
|
||||
|
||||
// y + -1*x == 0
|
||||
expr* a0 = 0, *a1 = 0, *x = 0;
|
||||
if (arith.is_zero(e2) && arith.is_add(e1, a0, a1)) {
|
||||
if (arith.is_times_minus_one(a1, x)) {
|
||||
e1 = a0;
|
||||
e2 = x;
|
||||
}
|
||||
else if (arith.is_times_minus_one(a0, x)) {
|
||||
e1 = a1;
|
||||
e2 = x;
|
||||
}
|
||||
}
|
||||
equiv.merge(e1, e2);
|
||||
}
|
||||
else {
|
||||
if (j < i) {
|
||||
v[j] = v.get(i);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
v.shrink(j);
|
||||
}
|
||||
|
||||
/**
|
||||
* converts equivalence classes to equalities
|
||||
*/
|
||||
void equiv_to_expr(expr_equiv_class &equiv, expr_ref_vector &out) {
|
||||
ast_manager &m = out.get_manager();
|
||||
for (auto eq_class : equiv) {
|
||||
expr *rep = nullptr;
|
||||
for (expr *elem : eq_class) {
|
||||
if (!m.is_value(elem)) {
|
||||
rep = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(rep);
|
||||
for (expr *elem : eq_class) {
|
||||
if (rep != elem) {
|
||||
out.push_back (m.mk_eq (rep, elem));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* expands equivalence classes to all derivable equalities
|
||||
*/
|
||||
bool equiv_to_expr_full(expr_equiv_class &equiv, expr_ref_vector &out) {
|
||||
ast_manager &m = out.get_manager();
|
||||
bool dirty = false;
|
||||
for (auto eq_class : equiv) {
|
||||
for (auto a = eq_class.begin(), end = eq_class.end(); a != end; ++a) {
|
||||
expr_equiv_class::iterator b(a);
|
||||
for (++b; b != end; ++b) {
|
||||
out.push_back(m.mk_eq(*a, *b));
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirty;
|
||||
}
|
183
src/ast/factor_equivs.h
Normal file
183
src/ast/factor_equivs.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Arie Gurfinkel
|
||||
|
||||
Module Name:
|
||||
|
||||
factor_equivs.h
|
||||
|
||||
Abstract:
|
||||
Factor equivalence classes out of an expression.
|
||||
|
||||
"Equivalence class structure" for objs. Uses a union_find structure internally.
|
||||
Operations are :
|
||||
-Declare a new equivalence class with a single element
|
||||
-Merge two equivalence classes
|
||||
-Retrieve whether two elements are in the same equivalence class
|
||||
-Iterate on all the elements of the equivalence class of a given element
|
||||
-Iterate on all equivalence classes (and then within them)
|
||||
|
||||
Author:
|
||||
|
||||
Julien Braine
|
||||
Arie Gurfinkel
|
||||
|
||||
Revision History:
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FACTOR_EQUIVS_H_
|
||||
#define FACTOR_EQUIVS_H_
|
||||
|
||||
#include "util/union_find.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
///All functions naturally add their parameters to the union_find class
|
||||
template<typename OBJ, typename Manager>
|
||||
class obj_equiv_class {
|
||||
basic_union_find m_uf;
|
||||
obj_map<OBJ, unsigned> m_to_int;
|
||||
ref_vector<OBJ, Manager> m_to_obj;
|
||||
|
||||
unsigned add_elem_impl(OBJ*o) {
|
||||
unsigned id = m_to_obj.size();
|
||||
m_to_int.insert(o, id);
|
||||
m_to_obj.push_back(o);
|
||||
return id;
|
||||
}
|
||||
unsigned add_if_not_there(OBJ*o) {
|
||||
unsigned id;
|
||||
if(!m_to_int.find(o, id)) {
|
||||
id = add_elem_impl(o);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public:
|
||||
class iterator;
|
||||
class equiv_iterator;
|
||||
friend class iterator;
|
||||
friend class equiv_iterator;
|
||||
|
||||
obj_equiv_class(Manager& m) : m_to_obj(m) {}
|
||||
|
||||
void add_elem(OBJ*o) {
|
||||
SASSERT(!m_to_int.find(o));
|
||||
add_elem_impl(o);
|
||||
}
|
||||
|
||||
//Invalidates all iterators
|
||||
void merge(OBJ* a, OBJ* b) {
|
||||
unsigned v1 = add_if_not_there(a);
|
||||
unsigned v2 = add_if_not_there(b);
|
||||
unsigned tmp1 = m_uf.find(v1);
|
||||
unsigned tmp2 = m_uf.find(v2);
|
||||
m_uf.merge(tmp1, tmp2);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_uf.reset();
|
||||
m_to_int.reset();
|
||||
m_to_obj.reset();
|
||||
}
|
||||
|
||||
bool are_equiv(OBJ*a, OBJ*b) {
|
||||
unsigned id1 = add_if_not_there(a);
|
||||
unsigned id2 = add_if_not_there(b);
|
||||
return m_uf.find(id1) == m_uf.find(id2);
|
||||
}
|
||||
|
||||
class iterator {
|
||||
friend class obj_equiv_class;
|
||||
private :
|
||||
const obj_equiv_class& m_ouf;
|
||||
unsigned m_curr_id;
|
||||
bool m_first;
|
||||
iterator(const obj_equiv_class& uf, unsigned id, bool f) :
|
||||
m_ouf(uf), m_curr_id(id), m_first(f) {}
|
||||
public :
|
||||
OBJ*operator*() {return m_ouf.m_to_obj[m_curr_id];}
|
||||
|
||||
iterator& operator++() {
|
||||
m_curr_id = m_ouf.m_uf.next(m_curr_id);
|
||||
m_first = false;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const iterator& o) {
|
||||
SASSERT(&m_ouf == &o.m_ouf);
|
||||
return m_first == o.m_first && m_curr_id == o.m_curr_id;
|
||||
}
|
||||
bool operator!=(const iterator& o) {return !(*this == o);}
|
||||
};
|
||||
|
||||
iterator begin(OBJ*o) {
|
||||
unsigned id = add_if_not_there(o);
|
||||
return iterator(*this, id, true);
|
||||
}
|
||||
iterator end(OBJ*o) {
|
||||
unsigned id = add_if_not_there(o);
|
||||
return iterator(*this, id, false);
|
||||
}
|
||||
|
||||
class eq_class {
|
||||
private :
|
||||
iterator m_begin;
|
||||
iterator m_end;
|
||||
public :
|
||||
eq_class(const iterator& a, const iterator& b) : m_begin(a), m_end(b) {}
|
||||
iterator begin() {return m_begin;}
|
||||
iterator end() {return m_end;}
|
||||
};
|
||||
|
||||
class equiv_iterator {
|
||||
friend class obj_equiv_class;
|
||||
private :
|
||||
const obj_equiv_class& m_ouf;
|
||||
unsigned m_rootnb;
|
||||
equiv_iterator(const obj_equiv_class& uf, unsigned nb) :
|
||||
m_ouf(uf), m_rootnb(nb) {
|
||||
while(m_rootnb != m_ouf.m_to_obj.size() &&
|
||||
m_ouf.m_uf.is_root(m_rootnb) != true)
|
||||
{ m_rootnb++; }
|
||||
}
|
||||
public :
|
||||
eq_class operator*() {
|
||||
return eq_class(iterator(m_ouf, m_rootnb, true),
|
||||
iterator(m_ouf, m_rootnb, false));
|
||||
}
|
||||
equiv_iterator& operator++() {
|
||||
do {
|
||||
m_rootnb++;
|
||||
} while(m_rootnb != m_ouf.m_to_obj.size() &&
|
||||
m_ouf.m_uf.is_root(m_rootnb) != true);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const equiv_iterator& o) {
|
||||
SASSERT(&m_ouf == &o.m_ouf);
|
||||
return m_rootnb == o.m_rootnb;
|
||||
}
|
||||
bool operator!=(const equiv_iterator& o) {return !(*this == o);}
|
||||
};
|
||||
|
||||
equiv_iterator begin() {return equiv_iterator(*this, 0);}
|
||||
equiv_iterator end() {return equiv_iterator(*this, m_to_obj.size());}
|
||||
};
|
||||
|
||||
typedef obj_equiv_class<expr, ast_manager> expr_equiv_class;
|
||||
|
||||
|
||||
/**
|
||||
* Factors input vector v into equivalence classes and the rest
|
||||
*/
|
||||
void factor_eqs(expr_ref_vector &v, expr_equiv_class &equiv);
|
||||
/**
|
||||
* converts equivalence classes to equalities
|
||||
*/
|
||||
void equiv_to_expr(expr_equiv_class &equiv, expr_ref_vector &out);
|
||||
|
||||
/**
|
||||
* expands equivalence classes to all derivable equalities
|
||||
*/
|
||||
bool equiv_to_expr_full(expr_equiv_class &equiv, expr_ref_vector &out);
|
||||
|
||||
|
||||
#endif
|
|
@ -17,7 +17,7 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include"for_each_ast.h"
|
||||
#include "ast/for_each_ast.h"
|
||||
|
||||
struct ast_counter_proc {
|
||||
unsigned m_num;
|
||||
|
|
|
@ -19,9 +19,9 @@ Revision History:
|
|||
#ifndef FOR_EACH_AST_H_
|
||||
#define FOR_EACH_AST_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"trace.h"
|
||||
#include"map.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/trace.h"
|
||||
#include "util/map.h"
|
||||
|
||||
template<typename T>
|
||||
bool for_each_ast_args(ptr_vector<ast> & stack, ast_mark & visited, unsigned num_args, T * const * args) {
|
||||
|
|
|
@ -17,7 +17,7 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include"for_each_expr.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
|
||||
struct expr_counter_proc {
|
||||
unsigned m_num;
|
||||
|
|
|
@ -19,8 +19,8 @@ Revision History:
|
|||
#ifndef FOR_EACH_EXPR_H_
|
||||
#define FOR_EACH_EXPR_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"trace.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/trace.h"
|
||||
|
||||
template<typename ForEachProc, typename ExprMark, bool MarkAll, bool IgnorePatterns>
|
||||
void for_each_expr_core(ForEachProc & proc, ExprMark & visited, expr * n) {
|
||||
|
|
|
@ -16,8 +16,8 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"format.h"
|
||||
#include"recurse_expr_def.h"
|
||||
#include "ast/format.h"
|
||||
#include "ast/recurse_expr_def.h"
|
||||
|
||||
namespace format_ns {
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef FORMAT_H_
|
||||
#define FORMAT_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
namespace format_ns {
|
||||
typedef app format;
|
||||
|
|
|
@ -5,7 +5,7 @@ z3_add_component(fpa
|
|||
fpa2bv_rewriter.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
ast
|
||||
simplifier
|
||||
rewriter
|
||||
model
|
||||
util
|
||||
PYG_FILES
|
||||
|
|
|
@ -18,12 +18,12 @@ Notes:
|
|||
--*/
|
||||
#include<math.h>
|
||||
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"well_sorted.h"
|
||||
#include"th_rewriter.h"
|
||||
#include"fpa_rewriter.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/fpa_rewriter.h"
|
||||
|
||||
#include"bv2fpa_converter.h"
|
||||
#include "ast/fpa/bv2fpa_converter.h"
|
||||
|
||||
|
||||
bv2fpa_converter::bv2fpa_converter(ast_manager & m) :
|
||||
|
|
|
@ -19,11 +19,11 @@ Notes:
|
|||
#ifndef BV2FPA_CONVERTER_H_
|
||||
#define BV2FPA_CONVERTER_H_
|
||||
|
||||
#include"fpa_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"th_rewriter.h"
|
||||
#include"model_core.h"
|
||||
#include"fpa2bv_converter.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "model/model_core.h"
|
||||
#include "ast/fpa/fpa2bv_converter.h"
|
||||
|
||||
|
||||
class bv2fpa_converter {
|
||||
|
|
|
@ -18,12 +18,12 @@ Notes:
|
|||
--*/
|
||||
#include<math.h>
|
||||
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"well_sorted.h"
|
||||
#include"th_rewriter.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
|
||||
#include"fpa2bv_converter.h"
|
||||
#include"fpa_rewriter.h"
|
||||
#include "ast/fpa/fpa2bv_converter.h"
|
||||
#include "ast/rewriter/fpa_rewriter.h"
|
||||
|
||||
#define BVULT(X,Y,R) { expr_ref bvult_eq(m), bvult_not(m); m_simp.mk_eq(X, Y, bvult_eq); m_simp.mk_not(bvult_eq, bvult_not); expr_ref t(m); t = m_bv_util.mk_ule(X,Y); m_simp.mk_and(t, bvult_not, R); }
|
||||
|
||||
|
@ -1476,6 +1476,10 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
mk_ite(c71, zero_cond, z, v7);
|
||||
|
||||
// else comes the fused multiplication.
|
||||
expr_ref one_1(m), zero_1(m);
|
||||
one_1 = m_bv_util.mk_numeral(1, 1);
|
||||
zero_1 = m_bv_util.mk_numeral(0, 1);
|
||||
|
||||
unsigned ebits = m_util.get_ebits(f->get_range());
|
||||
unsigned sbits = m_util.get_sbits(f->get_range());
|
||||
|
||||
|
@ -1516,7 +1520,8 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
mul_sgn = m_bv_util.mk_bv_xor(2, signs);
|
||||
dbg_decouple("fpa2bv_fma_mul_sgn", mul_sgn);
|
||||
|
||||
mul_exp = m_bv_util.mk_bv_add(m_bv_util.mk_bv_sub(a_exp_ext, a_lz_ext),
|
||||
mul_exp = m_bv_util.mk_bv_add(
|
||||
m_bv_util.mk_bv_sub(a_exp_ext, a_lz_ext),
|
||||
m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext));
|
||||
dbg_decouple("fpa2bv_fma_mul_exp", mul_exp);
|
||||
|
||||
|
@ -1529,11 +1534,15 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
// The product has the form [-1][0].[2*sbits - 2].
|
||||
|
||||
// Extend c
|
||||
c_sig = m_bv_util.mk_zero_extend(1, m_bv_util.mk_concat(c_sig, m_bv_util.mk_numeral(0, sbits-1)));
|
||||
expr_ref c_sig_ext(m);
|
||||
c_sig_ext = m_bv_util.mk_zero_extend(1, m_bv_util.mk_concat(c_sig, m_bv_util.mk_numeral(0, sbits+2)));
|
||||
c_exp_ext = m_bv_util.mk_bv_sub(c_exp_ext, c_lz_ext);
|
||||
mul_sig = m_bv_util.mk_concat(mul_sig, m_bv_util.mk_numeral(0, 3));
|
||||
|
||||
SASSERT(m_bv_util.get_bv_size(mul_sig) == 2 * sbits);
|
||||
SASSERT(m_bv_util.get_bv_size(c_sig) == 2 * sbits);
|
||||
SASSERT(m_bv_util.get_bv_size(mul_sig) == 2*sbits+3);
|
||||
SASSERT(m_bv_util.get_bv_size(c_sig_ext) == 2*sbits+3);
|
||||
dbg_decouple("fpa2bv_fma_c_sig_ext", c_sig_ext);
|
||||
dbg_decouple("fpa2bv_fma_c_exp_ext", c_exp_ext);
|
||||
|
||||
expr_ref swap_cond(m);
|
||||
swap_cond = m_bv_util.mk_sle(mul_exp, c_exp_ext);
|
||||
|
@ -1542,10 +1551,10 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
|
||||
expr_ref e_sgn(m), e_sig(m), e_exp(m), f_sgn(m), f_sig(m), f_exp(m);
|
||||
m_simp.mk_ite(swap_cond, c_sgn, mul_sgn, e_sgn);
|
||||
m_simp.mk_ite(swap_cond, c_sig, mul_sig, e_sig); // has 2 * sbits
|
||||
m_simp.mk_ite(swap_cond, c_sig_ext, mul_sig, e_sig); // has 2 * sbits + 3
|
||||
m_simp.mk_ite(swap_cond, c_exp_ext, mul_exp, e_exp); // has ebits + 2
|
||||
m_simp.mk_ite(swap_cond, mul_sgn, c_sgn, f_sgn);
|
||||
m_simp.mk_ite(swap_cond, mul_sig, c_sig, f_sig); // has 2 * sbits
|
||||
m_simp.mk_ite(swap_cond, mul_sig, c_sig_ext, f_sig); // has 2 * sbits + 3
|
||||
m_simp.mk_ite(swap_cond, mul_exp, c_exp_ext, f_exp); // has ebits + 2
|
||||
|
||||
SASSERT(is_well_sorted(m, e_sgn));
|
||||
|
@ -1555,11 +1564,16 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
SASSERT(is_well_sorted(m, f_sig));
|
||||
SASSERT(is_well_sorted(m, f_exp));
|
||||
|
||||
SASSERT(m_bv_util.get_bv_size(e_sig) == 2 * sbits);
|
||||
SASSERT(m_bv_util.get_bv_size(f_sig) == 2 * sbits);
|
||||
SASSERT(m_bv_util.get_bv_size(e_sig) == 2*sbits+3);
|
||||
SASSERT(m_bv_util.get_bv_size(f_sig) == 2*sbits+3);
|
||||
SASSERT(m_bv_util.get_bv_size(e_exp) == ebits + 2);
|
||||
SASSERT(m_bv_util.get_bv_size(f_exp) == ebits + 2);
|
||||
|
||||
dbg_decouple("fpa2bv_fma_e_sig", e_sig);
|
||||
dbg_decouple("fpa2bv_fma_e_exp", e_exp);
|
||||
dbg_decouple("fpa2bv_fma_f_sig", f_sig);
|
||||
dbg_decouple("fpa2bv_fma_f_exp", f_exp);
|
||||
|
||||
expr_ref res_sgn(m), res_sig(m), res_exp(m);
|
||||
|
||||
expr_ref exp_delta(m);
|
||||
|
@ -1568,7 +1582,7 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
|
||||
// cap the delta
|
||||
expr_ref cap(m), cap_le_delta(m);
|
||||
cap = m_bv_util.mk_numeral(2*sbits, ebits+2);
|
||||
cap = m_bv_util.mk_numeral(2*sbits+3, ebits+2);
|
||||
cap_le_delta = m_bv_util.mk_ule(cap, exp_delta);
|
||||
m_simp.mk_ite(cap_le_delta, cap, exp_delta, exp_delta);
|
||||
SASSERT(m_bv_util.get_bv_size(exp_delta) == ebits+2);
|
||||
|
@ -1576,61 +1590,63 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
dbg_decouple("fpa2bv_fma_add_exp_delta_capped", exp_delta);
|
||||
|
||||
// Alignment shift with sticky bit computation.
|
||||
expr_ref shifted_big(m), shifted_f_sig(m), sticky_raw(m);
|
||||
expr_ref shifted_big(m), shifted_f_sig(m);
|
||||
expr_ref alignment_sticky_raw(m), alignment_sticky(m);
|
||||
shifted_big = m_bv_util.mk_bv_lshr(
|
||||
m_bv_util.mk_concat(f_sig, m_bv_util.mk_numeral(0, sbits)),
|
||||
m_bv_util.mk_zero_extend((3*sbits)-(ebits+2), exp_delta));
|
||||
shifted_f_sig = m_bv_util.mk_extract(3*sbits-1, sbits, shifted_big);
|
||||
sticky_raw = m_bv_util.mk_extract(sbits-1, 0, shifted_big);
|
||||
SASSERT(m_bv_util.get_bv_size(shifted_f_sig) == 2 * sbits);
|
||||
SASSERT(is_well_sorted(m, shifted_f_sig));
|
||||
|
||||
expr_ref sticky(m);
|
||||
sticky = m_bv_util.mk_zero_extend(2*sbits-1, m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sticky_raw.get()));
|
||||
SASSERT(is_well_sorted(m, sticky));
|
||||
dbg_decouple("fpa2bv_fma_f_sig_sticky_raw", sticky_raw);
|
||||
dbg_decouple("fpa2bv_fma_f_sig_sticky", sticky);
|
||||
|
||||
expr * or_args[2] = { shifted_f_sig, sticky };
|
||||
shifted_f_sig = m_bv_util.mk_bv_or(2, or_args);
|
||||
m_bv_util.mk_zero_extend((3*sbits+3)-(ebits+2), exp_delta));
|
||||
shifted_f_sig = m_bv_util.mk_extract(3*sbits+2, sbits, shifted_big);
|
||||
alignment_sticky_raw = m_bv_util.mk_extract(sbits-1, 0, shifted_big);
|
||||
alignment_sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, alignment_sticky_raw.get());
|
||||
dbg_decouple("fpa2bv_fma_shifted_f_sig", shifted_f_sig);
|
||||
dbg_decouple("fpa2bv_fma_f_sig_alignment_sticky", alignment_sticky);
|
||||
SASSERT(is_well_sorted(m, alignment_sticky));
|
||||
SASSERT(m_bv_util.get_bv_size(shifted_f_sig) == 2*sbits+3);
|
||||
SASSERT(is_well_sorted(m, shifted_f_sig));
|
||||
|
||||
// Significant addition.
|
||||
// Two extra bits for catching the overflow.
|
||||
// Two extra bits for the sign and for catching overflows.
|
||||
e_sig = m_bv_util.mk_zero_extend(2, e_sig);
|
||||
shifted_f_sig = m_bv_util.mk_zero_extend(2, shifted_f_sig);
|
||||
|
||||
expr_ref eq_sgn(m);
|
||||
m_simp.mk_eq(e_sgn, f_sgn, eq_sgn);
|
||||
dbg_decouple("fpa2bv_fma_eq_sgn", eq_sgn);
|
||||
|
||||
SASSERT(m_bv_util.get_bv_size(e_sig) == 2*sbits + 2);
|
||||
SASSERT(m_bv_util.get_bv_size(shifted_f_sig) == 2*sbits + 2);
|
||||
SASSERT(m_bv_util.get_bv_size(e_sig) == 2*sbits+5);
|
||||
SASSERT(m_bv_util.get_bv_size(shifted_f_sig) == 2*sbits+5);
|
||||
|
||||
dbg_decouple("fpa2bv_fma_add_e_sig", e_sig);
|
||||
dbg_decouple("fpa2bv_fma_add_shifted_f_sig", shifted_f_sig);
|
||||
|
||||
expr_ref sum(m), e_plus_f(m), e_minus_f(m);
|
||||
expr_ref sum(m), e_plus_f(m), e_minus_f(m), sticky_wide(m);
|
||||
sticky_wide = m_bv_util.mk_zero_extend(2*sbits+4, alignment_sticky);
|
||||
e_plus_f = m_bv_util.mk_bv_add(e_sig, shifted_f_sig);
|
||||
e_minus_f = m_bv_util.mk_bv_sub(e_sig, shifted_f_sig),
|
||||
m_simp.mk_ite(eq_sgn, e_plus_f, e_minus_f, sum);
|
||||
e_plus_f = m.mk_ite(m.mk_eq(m_bv_util.mk_extract(0, 0, e_plus_f), zero_1),
|
||||
m_bv_util.mk_bv_add(e_plus_f, sticky_wide),
|
||||
e_plus_f);
|
||||
e_minus_f = m_bv_util.mk_bv_sub(e_sig, shifted_f_sig);
|
||||
e_minus_f = m.mk_ite(m.mk_eq(m_bv_util.mk_extract(0, 0, e_minus_f), zero_1),
|
||||
m_bv_util.mk_bv_sub(e_minus_f, sticky_wide),
|
||||
e_minus_f);
|
||||
SASSERT(is_well_sorted(m, shifted_f_sig));
|
||||
dbg_decouple("fpa2bv_fma_f_sig_or_sticky", shifted_f_sig);
|
||||
|
||||
m_simp.mk_ite(eq_sgn, e_plus_f, e_minus_f, sum);
|
||||
SASSERT(m_bv_util.get_bv_size(sum) == 2*sbits+5);
|
||||
SASSERT(is_well_sorted(m, sum));
|
||||
|
||||
dbg_decouple("fpa2bv_fma_add_sum", sum);
|
||||
|
||||
expr_ref sign_bv(m), n_sum(m);
|
||||
sign_bv = m_bv_util.mk_extract(2*sbits+1, 2*sbits+1, sum);
|
||||
sign_bv = m_bv_util.mk_extract(2*sbits+4, 2*sbits+4, sum);
|
||||
n_sum = m_bv_util.mk_bv_neg(sum);
|
||||
|
||||
expr_ref res_sig_eq(m), sig_abs(m), one_1(m);
|
||||
one_1 = m_bv_util.mk_numeral(1, 1);
|
||||
m_simp.mk_eq(sign_bv, one_1, res_sig_eq);
|
||||
m_simp.mk_ite(res_sig_eq, n_sum, sum, sig_abs);
|
||||
dbg_decouple("fpa2bv_fma_add_sign_bv", sign_bv);
|
||||
dbg_decouple("fpa2bv_fma_add_n_sum", n_sum);
|
||||
dbg_decouple("fpa2bv_fma_add_sig_abs", sig_abs);
|
||||
|
||||
res_exp = e_exp;
|
||||
expr_ref res_sig_eq(m), sig_abs(m);
|
||||
m_simp.mk_eq(sign_bv, one_1, res_sig_eq);
|
||||
m_simp.mk_ite(res_sig_eq, n_sum, sum, sig_abs);
|
||||
dbg_decouple("fpa2bv_fma_add_sig_abs", sig_abs);
|
||||
|
||||
family_id bvfid = m_bv_util.get_fid();
|
||||
expr_ref res_sgn_c1(m), res_sgn_c2(m), res_sgn_c3(m);
|
||||
|
@ -1643,44 +1659,76 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
|
|||
res_sgn_c3 = m.mk_app(bvfid, OP_BAND, e_sgn, f_sgn);
|
||||
expr * res_sgn_or_args[3] = { res_sgn_c1, res_sgn_c2, res_sgn_c3 };
|
||||
res_sgn = m_bv_util.mk_bv_or(3, res_sgn_or_args);
|
||||
dbg_decouple("fpa2bv_fma_res_sgn", res_sgn);
|
||||
|
||||
expr_ref is_sig_neg(m);
|
||||
is_sig_neg = m.mk_eq(one_1, m_bv_util.mk_extract(2*sbits+4, 2*sbits+4, sig_abs));
|
||||
sig_abs = m.mk_ite(is_sig_neg, m_bv_util.mk_bv_neg(sig_abs), sig_abs);
|
||||
dbg_decouple("fpa2bv_fma_is_sig_neg", is_sig_neg);
|
||||
|
||||
// Result could have overflown into 4.xxx.
|
||||
SASSERT(m_bv_util.get_bv_size(sig_abs) == 2 * sbits + 2);
|
||||
expr_ref ovfl_into_4(m);
|
||||
ovfl_into_4 = m.mk_eq(m_bv_util.mk_extract(2 * sbits + 1, 2 * sbits, sig_abs),
|
||||
m_bv_util.mk_numeral(1, 2));
|
||||
dbg_decouple("fpa2bv_fma_ovfl_into_4", ovfl_into_4);
|
||||
if (sbits > 5) {
|
||||
expr_ref sticky_raw(m), sig_upper(m), sticky_redd(m), res_sig_norm(m);
|
||||
sticky_raw = m_bv_util.mk_extract(sbits - 4, 0, sig_abs);
|
||||
sig_upper = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_upper) == sbits + 4);
|
||||
sticky_redd = m.mk_app(bvfid, OP_BREDOR, sticky_raw.get());
|
||||
sticky = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd);
|
||||
expr * res_or_args[2] = { sig_upper, sticky };
|
||||
res_sig_norm = m_bv_util.mk_bv_or(2, res_or_args);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_abs) == 2*sbits+5);
|
||||
expr_ref extra(m), extra_is_zero(m);
|
||||
extra = m_bv_util.mk_extract(2*sbits+4, 2*sbits+3, sig_abs);
|
||||
extra_is_zero = m.mk_eq(extra, m_bv_util.mk_numeral(0, 2));
|
||||
dbg_decouple("fpa2bv_fma_extra", extra);
|
||||
|
||||
expr_ref sticky_raw_ovfl(m), sig_upper_ovfl(m), sticky_redd_ovfl(m), sticky_ovfl(m), res_sig_ovfl(m);
|
||||
sticky_raw_ovfl = m_bv_util.mk_extract(sbits - 4, 0, sig_abs);
|
||||
sig_upper_ovfl = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_upper_ovfl) == sbits + 4);
|
||||
sticky_redd_ovfl = m.mk_app(bvfid, OP_BREDOR, sticky_raw_ovfl.get());
|
||||
sticky_ovfl = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd_ovfl);
|
||||
expr * res_or_args_ovfl[2] = { sig_upper_ovfl, sticky_ovfl };
|
||||
res_sig_ovfl = m_bv_util.mk_bv_or(2, res_or_args_ovfl);
|
||||
res_exp = m.mk_ite(extra_is_zero, e_exp, m_bv_util.mk_bv_add(e_exp, m_bv_util.mk_numeral(1, ebits + 2)));
|
||||
|
||||
res_sig = m.mk_ite(ovfl_into_4, res_sig_ovfl, res_sig_norm);
|
||||
res_exp = m.mk_ite(ovfl_into_4, m_bv_util.mk_bv_add(res_exp, m_bv_util.mk_numeral(1, ebits+2)),
|
||||
res_exp);
|
||||
}
|
||||
else {
|
||||
unsigned too_short = 6 - sbits;
|
||||
// Renormalize
|
||||
expr_ref zero_e2(m), min_exp(m), sig_lz(m), max_exp_delta(m), sig_lz_capped(m), renorm_delta(m);
|
||||
zero_e2 = m_bv_util.mk_numeral(0, ebits + 2);
|
||||
mk_min_exp(ebits, min_exp);
|
||||
min_exp = m_bv_util.mk_sign_extend(2, min_exp);
|
||||
mk_leading_zeros(sig_abs, ebits+2, sig_lz);
|
||||
sig_lz = m_bv_util.mk_bv_sub(sig_lz, m_bv_util.mk_numeral(2, ebits+2));
|
||||
max_exp_delta = m_bv_util.mk_bv_sub(res_exp, min_exp);
|
||||
sig_lz_capped = m.mk_ite(m_bv_util.mk_sle(sig_lz, max_exp_delta), sig_lz, max_exp_delta);
|
||||
renorm_delta = m.mk_ite(m_bv_util.mk_sle(zero_e2, sig_lz_capped), sig_lz_capped, zero_e2);
|
||||
res_exp = m_bv_util.mk_bv_sub(res_exp, renorm_delta);
|
||||
sig_abs = m_bv_util.mk_bv_shl(sig_abs, m_bv_util.mk_zero_extend(2*sbits+3-ebits, renorm_delta));
|
||||
dbg_decouple("fpa2bv_fma_min_exp", min_exp);
|
||||
dbg_decouple("fpa2bv_fma_max_exp_delta", max_exp_delta);
|
||||
dbg_decouple("fpa2bv_fma_sig_lz", sig_lz);
|
||||
dbg_decouple("fpa2bv_fma_sig_lz_capped", sig_lz_capped);
|
||||
dbg_decouple("fpa2bv_fma_renorm_delta", renorm_delta);
|
||||
|
||||
unsigned too_short = 0;
|
||||
if (sbits < 5) {
|
||||
too_short = 6 - sbits + 1;
|
||||
sig_abs = m_bv_util.mk_concat(sig_abs, m_bv_util.mk_numeral(0, too_short));
|
||||
res_sig = m_bv_util.mk_extract(sbits + 3, 0, sig_abs);
|
||||
}
|
||||
dbg_decouple("fpa2bv_fma_add_sum_sticky", sticky);
|
||||
dbg_decouple("fpa2bv_fma_sig_abs", sig_abs);
|
||||
|
||||
expr_ref sig_abs_h1(m), sticky_h1(m), sticky_h1_red(m), sig_abs_h1_f(m), res_sig_1(m);
|
||||
sticky_h1 = m_bv_util.mk_extract(sbits+too_short-2, 0, sig_abs);
|
||||
sig_abs_h1 = m_bv_util.mk_extract(2*sbits+too_short+4, sbits-1+too_short, sig_abs);
|
||||
sticky_h1_red = m_bv_util.mk_zero_extend(sbits+5, m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sticky_h1.get()));
|
||||
expr * sticky_h1_red_args[2] = { sig_abs_h1, sticky_h1_red };
|
||||
sig_abs_h1_f = m_bv_util.mk_bv_or(2, sticky_h1_red_args);
|
||||
res_sig_1 = m_bv_util.mk_extract(sbits+3, 0, sig_abs_h1_f);
|
||||
SASSERT(m_bv_util.get_bv_size(sticky_h1) == sbits+too_short-1);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_abs_h1) == sbits+6);
|
||||
SASSERT(m_bv_util.get_bv_size(sticky_h1_red) == sbits+6);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_abs_h1_f) == sbits+6);
|
||||
SASSERT(m_bv_util.get_bv_size(res_sig_1) == sbits+4);
|
||||
|
||||
expr_ref sig_abs_h2(m), sticky_h2(m), sticky_h2_red(m), sig_abs_h2_f(m), res_sig_2(m);
|
||||
sticky_h2 = m_bv_util.mk_extract(sbits+too_short-1, 0, sig_abs);
|
||||
sig_abs_h2 = m_bv_util.mk_extract(2*sbits+too_short+4, sbits+too_short, sig_abs);
|
||||
sticky_h2_red = m_bv_util.mk_zero_extend(sbits+4, m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sticky_h1.get()));
|
||||
expr * sticky_h2_red_args[2] = { sig_abs_h2, sticky_h2_red };
|
||||
sig_abs_h2_f = m_bv_util.mk_zero_extend(1, m_bv_util.mk_bv_or(2, sticky_h2_red_args));
|
||||
res_sig_2 = m_bv_util.mk_extract(sbits+3, 0, sig_abs_h2_f);
|
||||
SASSERT(m_bv_util.get_bv_size(sticky_h2) == sbits+too_short);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_abs_h2) == sbits+5);
|
||||
SASSERT(m_bv_util.get_bv_size(sticky_h2_red) == sbits+5);
|
||||
SASSERT(m_bv_util.get_bv_size(sig_abs_h2_f) == sbits+6);
|
||||
SASSERT(m_bv_util.get_bv_size(res_sig_2) == sbits+4);
|
||||
|
||||
res_sig = m.mk_ite(extra_is_zero, res_sig_1, res_sig_2);
|
||||
|
||||
dbg_decouple("fpa2bv_fma_res_sig", res_sig);
|
||||
dbg_decouple("fpa2bv_fma_res_exp", res_exp);
|
||||
SASSERT(m_bv_util.get_bv_size(res_sig) == sbits + 4);
|
||||
|
||||
expr_ref is_zero_sig(m), nil_sbits4(m);
|
||||
|
@ -2666,13 +2714,21 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con
|
|||
SASSERT(m_util.is_bv2rm(args[0]));
|
||||
expr * bv_rm = to_app(args[0])->get_arg(0);
|
||||
|
||||
rational e;
|
||||
if (!m_arith_util.is_numeral(args[1], e))
|
||||
UNREACHABLE();
|
||||
SASSERT((m_arith_util.is_int(args[1]) && m_arith_util.is_real(args[2])) ||
|
||||
(m_arith_util.is_real(args[1]) && m_arith_util.is_int(args[2])));
|
||||
|
||||
rational q;
|
||||
if (!m_arith_util.is_numeral(args[2], q))
|
||||
UNREACHABLE();
|
||||
rational q, e;
|
||||
|
||||
if (m_arith_util.is_int(args[1]) && m_arith_util.is_real(args[2])) {
|
||||
if (!m_arith_util.is_numeral(args[1], e) ||
|
||||
!m_arith_util.is_numeral(args[2], q))
|
||||
UNREACHABLE();
|
||||
}
|
||||
else {
|
||||
if (!m_arith_util.is_numeral(args[2], e) ||
|
||||
!m_arith_util.is_numeral(args[1], q))
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
SASSERT(e.is_int64());
|
||||
SASSERT(m_mpz_manager.eq(e.to_mpq().denominator(), 1));
|
||||
|
@ -3882,15 +3938,12 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
|||
SASSERT(m_bv_util.get_bv_size(sig) == sbits+4);
|
||||
SASSERT(m_bv_util.get_bv_size(exp) == ebits+2);
|
||||
|
||||
// bool UNFen = false;
|
||||
// bool OVFen = false;
|
||||
|
||||
expr_ref e_min(m), e_max(m);
|
||||
mk_min_exp(ebits, e_min);
|
||||
mk_max_exp(ebits, e_max);
|
||||
|
||||
TRACE("fpa2bv_dbg", tout << "e_min = " << mk_ismt2_pp(e_min, m) << std::endl <<
|
||||
"e_max = " << mk_ismt2_pp(e_max, m) << std::endl;);
|
||||
TRACE("fpa2bv_dbg", tout << "e_min = " << mk_ismt2_pp(e_min, m) << std::endl;
|
||||
tout << "e_max = " << mk_ismt2_pp(e_max, m) << std::endl;);
|
||||
|
||||
expr_ref OVF1(m), e_top_three(m), sigm1(m), e_eq_emax_and_sigm1(m), e_eq_emax(m);
|
||||
expr_ref e3(m), ne3(m), e2(m), e1(m), e21(m), one_1(m), h_exp(m), sh_exp(m), th_exp(m);
|
||||
|
@ -4003,7 +4056,6 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
|||
SASSERT(is_well_sorted(m, sig));
|
||||
SASSERT(m_bv_util.get_bv_size(sig) == sbits+2);
|
||||
|
||||
// CMW: The (OVF1 && OVFen) and (TINY && UNFen) cases are never taken.
|
||||
expr_ref ext_emin(m);
|
||||
ext_emin = m_bv_util.mk_zero_extend(2, e_min);
|
||||
m_simp.mk_ite(TINY, ext_emin, beta, exp);
|
||||
|
@ -4106,7 +4158,6 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
|||
dbg_decouple("fpa2bv_rnd_rm_is_to_neg", rm_is_to_neg);
|
||||
dbg_decouple("fpa2bv_rnd_rm_is_to_pos", rm_is_to_pos);
|
||||
|
||||
|
||||
expr_ref sgn_is_zero(m), zero1(m);
|
||||
zero1 = m_bv_util.mk_numeral(0, 1);
|
||||
m_simp.mk_eq(sgn, zero1, sgn_is_zero);
|
||||
|
|
|
@ -19,17 +19,17 @@ Notes:
|
|||
#ifndef FPA2BV_CONVERTER_H_
|
||||
#define FPA2BV_CONVERTER_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"ref_util.h"
|
||||
#include"fpa_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"pb_decl_plugin.h"
|
||||
#include"seq_decl_plugin.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "util/ref_util.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/dl_decl_plugin.h"
|
||||
#include "ast/pb_decl_plugin.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
|
||||
class fpa2bv_converter {
|
||||
public:
|
||||
|
@ -39,7 +39,7 @@ public:
|
|||
|
||||
protected:
|
||||
ast_manager & m;
|
||||
basic_simplifier_plugin m_simp;
|
||||
bool_rewriter m_simp;
|
||||
fpa_util m_util;
|
||||
bv_util m_bv_util;
|
||||
arith_util m_arith_util;
|
||||
|
|
|
@ -18,10 +18,10 @@ Notes:
|
|||
--*/
|
||||
|
||||
|
||||
#include"rewriter_def.h"
|
||||
#include"fpa2bv_rewriter.h"
|
||||
#include"cooperate.h"
|
||||
#include"fpa2bv_rewriter_params.hpp"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/fpa/fpa2bv_rewriter.h"
|
||||
#include "util/cooperate.h"
|
||||
#include "ast/fpa/fpa2bv_rewriter_params.hpp"
|
||||
|
||||
|
||||
fpa2bv_rewriter_cfg::fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p) :
|
||||
|
|
|
@ -20,9 +20,9 @@ Notes:
|
|||
#ifndef FPA2BV_REWRITER_H_
|
||||
#define FPA2BV_REWRITER_H_
|
||||
|
||||
#include"rewriter.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"fpa2bv_converter.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/fpa/fpa2bv_converter.h"
|
||||
|
||||
struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
|
|
|
@ -16,9 +16,9 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"fpa_decl_plugin.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
|
||||
fpa_decl_plugin::fpa_decl_plugin():
|
||||
m_values(m_fm),
|
||||
|
|
|
@ -19,11 +19,11 @@ Revision History:
|
|||
#ifndef fpa_decl_plugin_H_
|
||||
#define fpa_decl_plugin_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"id_gen.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"mpf.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/id_gen.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "util/mpf.h"
|
||||
|
||||
enum fpa_sort_kind {
|
||||
FLOATING_POINT_SORT,
|
||||
|
|
|
@ -16,9 +16,9 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"func_decl_dependencies.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"ast_util.h"
|
||||
#include "ast/func_decl_dependencies.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
struct collect_dependencies_proc {
|
||||
ast_manager & m_manager;
|
||||
|
|
|
@ -19,8 +19,8 @@ Revision History:
|
|||
#ifndef FUNC_DECL_DEPENDENCIES_H_
|
||||
#define FUNC_DECL_DEPENDENCIES_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
|
||||
// Set of dependencies
|
||||
typedef obj_hashtable<func_decl> func_decl_set;
|
||||
|
|
|
@ -16,9 +16,9 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"ast.h"
|
||||
#include"expr_delta_pair.h"
|
||||
#include"hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/expr_delta_pair.h"
|
||||
#include "util/hashtable.h"
|
||||
|
||||
class contains_vars {
|
||||
typedef hashtable<expr_delta_pair, obj_hash<expr_delta_pair>, default_eq<expr_delta_pair> > cache;
|
||||
|
|
52
src/ast/justified_expr.h
Normal file
52
src/ast/justified_expr.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
#ifndef JUSTIFIED_EXPR_H_
|
||||
#define JUSTIFIED_EXPR_H_
|
||||
|
||||
#include "ast/ast.h"
|
||||
|
||||
class justified_expr {
|
||||
ast_manager& m;
|
||||
expr* m_fml;
|
||||
proof* m_proof;
|
||||
public:
|
||||
justified_expr(ast_manager& m, expr* fml, proof* p):
|
||||
m(m),
|
||||
m_fml(fml),
|
||||
m_proof(p) {
|
||||
SASSERT(fml);
|
||||
m.inc_ref(fml);
|
||||
m.inc_ref(p);
|
||||
}
|
||||
|
||||
justified_expr& operator=(justified_expr const& other) {
|
||||
SASSERT(&m == &other.m);
|
||||
if (this != &other) {
|
||||
m.inc_ref(other.get_fml());
|
||||
m.inc_ref(other.get_proof());
|
||||
m.dec_ref(m_fml);
|
||||
m.dec_ref(m_proof);
|
||||
m_fml = other.get_fml();
|
||||
m_proof = other.get_proof();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
justified_expr(justified_expr const& other):
|
||||
m(other.m),
|
||||
m_fml(other.m_fml),
|
||||
m_proof(other.m_proof)
|
||||
{
|
||||
m.inc_ref(m_fml);
|
||||
m.inc_ref(m_proof);
|
||||
}
|
||||
|
||||
~justified_expr() {
|
||||
m.dec_ref(m_fml);
|
||||
m.dec_ref(m_proof);
|
||||
}
|
||||
|
||||
expr* get_fml() const { return m_fml; }
|
||||
proof* get_proof() const { return m_proof; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -18,8 +18,8 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"macro_substitution.h"
|
||||
#include"ref_util.h"
|
||||
#include "ast/macro_substitution.h"
|
||||
#include "util/ref_util.h"
|
||||
|
||||
typedef obj_map<func_decl, proof*> func_decl2proof;
|
||||
typedef obj_map<func_decl, expr_dependency*> func_decl2expr_dependency;
|
||||
|
|
|
@ -21,7 +21,7 @@ Notes:
|
|||
#ifndef MACRO_SUBSTITUTION_H_
|
||||
#define MACRO_SUBSTITUTION_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
class macro_substitution {
|
||||
ast_manager & m_manager;
|
||||
|
|
|
@ -5,5 +5,5 @@ z3_add_component(macros
|
|||
macro_util.cpp
|
||||
quasi_macros.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
simplifier
|
||||
rewriter
|
||||
)
|
||||
|
|
|
@ -17,100 +17,167 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include"macro_finder.h"
|
||||
#include"occurs.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include "ast/macros/macro_finder.h"
|
||||
#include "ast/occurs.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
|
||||
bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
return false;
|
||||
TRACE("macro_finder", tout << "processing: " << mk_pp(n, m_manager) << "\n";);
|
||||
TRACE("macro_finder", tout << "processing: " << mk_pp(n, m) << "\n";);
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
return m_util.is_simple_macro(body, num_decls, head, def);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Detect macros of the form
|
||||
\brief Detect macros of the form
|
||||
1- (forall (X) (= (+ (f X) (R X)) c))
|
||||
2- (forall (X) (<= (+ (f X) (R X)) c))
|
||||
3- (forall (X) (>= (+ (f X) (R X)) c))
|
||||
|
||||
The second and third cases are first converted into
|
||||
(forall (X) (= (f X) (+ c (* -1 (R x)) (k X))))
|
||||
and
|
||||
and
|
||||
(forall (X) (<= (k X) 0)) when case 2
|
||||
(forall (X) (>= (k X) 0)) when case 3
|
||||
|
||||
For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs.
|
||||
*/
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
return false;
|
||||
arith_simplifier_plugin * as = get_arith_simp();
|
||||
arith_util & autil = as->get_arith_util();
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
||||
if (!autil.is_le(body) && !autil.is_ge(body) && !m_manager.is_eq(body))
|
||||
if (!m_autil.is_le(body) && !m_autil.is_ge(body) && !m.is_eq(body))
|
||||
return false;
|
||||
if (!as->is_add(to_app(body)->get_arg(0)))
|
||||
if (!m_autil.is_add(to_app(body)->get_arg(0)))
|
||||
return false;
|
||||
app_ref head(m_manager);
|
||||
expr_ref def(m_manager);
|
||||
app_ref head(m);
|
||||
expr_ref def(m);
|
||||
bool inv = false;
|
||||
if (!m_util.is_arith_macro(body, num_decls, head, def, inv))
|
||||
return false;
|
||||
app_ref new_body(m_manager);
|
||||
|
||||
if (!inv || m_manager.is_eq(body))
|
||||
new_body = m_manager.mk_app(to_app(body)->get_decl(), head, def);
|
||||
else if (as->is_le(body))
|
||||
new_body = autil.mk_ge(head, def);
|
||||
else
|
||||
new_body = autil.mk_le(head, def);
|
||||
app_ref new_body(m);
|
||||
|
||||
quantifier_ref new_q(m_manager);
|
||||
new_q = m_manager.update_quantifier(to_quantifier(n), new_body);
|
||||
if (!inv || m.is_eq(body))
|
||||
new_body = m.mk_app(to_app(body)->get_decl(), head, def);
|
||||
else if (m_autil.is_le(body))
|
||||
new_body = m_autil.mk_ge(head, def);
|
||||
else
|
||||
new_body = m_autil.mk_le(head, def);
|
||||
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(to_quantifier(n), new_body);
|
||||
proof * new_pr = 0;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * rw = m_manager.mk_rewrite(n, new_q);
|
||||
new_pr = m_manager.mk_modus_ponens(pr, rw);
|
||||
if (m.proofs_enabled()) {
|
||||
proof * rw = m.mk_rewrite(n, new_q);
|
||||
new_pr = m.mk_modus_ponens(pr, rw);
|
||||
}
|
||||
if (m_manager.is_eq(body)) {
|
||||
expr_dependency * new_dep = dep;
|
||||
if (m.is_eq(body)) {
|
||||
return m_macro_manager.insert(head->get_decl(), new_q, new_pr, new_dep);
|
||||
}
|
||||
// is ge or le
|
||||
//
|
||||
TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";);
|
||||
func_decl * f = head->get_decl();
|
||||
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
||||
expr_ref_buffer new_rhs_args(m);
|
||||
expr_ref new_rhs2(m_autil.mk_add(def, k_app), m);
|
||||
expr * body1 = m.mk_eq(head, new_rhs2);
|
||||
expr * body2 = m.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0));
|
||||
quantifier * q1 = m.update_quantifier(new_q, body1);
|
||||
expr * patterns[1] = { m.mk_pattern(k_app) };
|
||||
quantifier * q2 = m.update_quantifier(new_q, 1, patterns, body2);
|
||||
new_exprs.push_back(q1);
|
||||
new_exprs.push_back(q2);
|
||||
if (m.proofs_enabled()) {
|
||||
// new_pr : new_q
|
||||
// rw : [rewrite] new_q ~ q1 & q2
|
||||
// mp : [modus_pones new_pr rw] q1 & q2
|
||||
// pr1 : [and-elim mp] q1
|
||||
// pr2 : [and-elim mp] q2
|
||||
app * q1q2 = m.mk_and(q1,q2);
|
||||
proof * rw = m.mk_oeq_rewrite(new_q, q1q2);
|
||||
proof * mp = m.mk_modus_ponens(new_pr, rw);
|
||||
proof * pr1 = m.mk_and_elim(mp, 0);
|
||||
proof * pr2 = m.mk_and_elim(mp, 1);
|
||||
new_prs.push_back(pr1);
|
||||
new_prs.push_back(pr2);
|
||||
}
|
||||
if (dep) {
|
||||
new_deps.push_back(new_dep);
|
||||
new_deps.push_back(new_dep);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
return false;
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
||||
if (!m_autil.is_le(body) && !m_autil.is_ge(body) && !m.is_eq(body))
|
||||
return false;
|
||||
if (!m_autil.is_add(to_app(body)->get_arg(0)))
|
||||
return false;
|
||||
app_ref head(m);
|
||||
expr_ref def(m);
|
||||
bool inv = false;
|
||||
if (!m_util.is_arith_macro(body, num_decls, head, def, inv))
|
||||
return false;
|
||||
app_ref new_body(m);
|
||||
|
||||
if (!inv || m.is_eq(body))
|
||||
new_body = m.mk_app(to_app(body)->get_decl(), head, def);
|
||||
else if (m_autil.is_le(body))
|
||||
new_body = m_autil.mk_ge(head, def);
|
||||
else
|
||||
new_body = m_autil.mk_le(head, def);
|
||||
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(to_quantifier(n), new_body);
|
||||
proof * new_pr = 0;
|
||||
if (m.proofs_enabled()) {
|
||||
proof * rw = m.mk_rewrite(n, new_q);
|
||||
new_pr = m.mk_modus_ponens(pr, rw);
|
||||
}
|
||||
if (m.is_eq(body)) {
|
||||
return m_macro_manager.insert(head->get_decl(), new_q, new_pr);
|
||||
}
|
||||
// is ge or le
|
||||
//
|
||||
TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";);
|
||||
func_decl * f = head->get_decl();
|
||||
func_decl * k = m_manager.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m_manager.mk_app(k, head->get_num_args(), head->get_args());
|
||||
expr_ref_buffer new_rhs_args(m_manager);
|
||||
expr_ref new_rhs2(m_manager);
|
||||
as->mk_add(def, k_app, new_rhs2);
|
||||
expr * body1 = m_manager.mk_eq(head, new_rhs2);
|
||||
expr * body2 = m_manager.mk_app(new_body->get_decl(), k_app, as->mk_numeral(rational(0)));
|
||||
quantifier * q1 = m_manager.update_quantifier(new_q, body1);
|
||||
expr * patterns[1] = { m_manager.mk_pattern(k_app) };
|
||||
quantifier * q2 = m_manager.update_quantifier(new_q, 1, patterns, body2);
|
||||
new_exprs.push_back(q1);
|
||||
new_exprs.push_back(q2);
|
||||
if (m_manager.proofs_enabled()) {
|
||||
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
||||
expr_ref_buffer new_rhs_args(m);
|
||||
expr_ref new_rhs2(m_autil.mk_add(def, k_app), m);
|
||||
expr * body1 = m.mk_eq(head, new_rhs2);
|
||||
expr * body2 = m.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0));
|
||||
quantifier * q1 = m.update_quantifier(new_q, body1);
|
||||
expr * patterns[1] = { m.mk_pattern(k_app) };
|
||||
quantifier * q2 = m.update_quantifier(new_q, 1, patterns, body2);
|
||||
proof* pr1 = 0, *pr2 = 0;
|
||||
if (m.proofs_enabled()) {
|
||||
// new_pr : new_q
|
||||
// rw : [rewrite] new_q ~ q1 & q2
|
||||
// mp : [modus_pones new_pr rw] q1 & q2
|
||||
// pr1 : [and-elim mp] q1
|
||||
// pr2 : [and-elim mp] q2
|
||||
app * q1q2 = m_manager.mk_and(q1,q2);
|
||||
proof * rw = m_manager.mk_oeq_rewrite(new_q, q1q2);
|
||||
proof * mp = m_manager.mk_modus_ponens(new_pr, rw);
|
||||
proof * pr1 = m_manager.mk_and_elim(mp, 0);
|
||||
proof * pr2 = m_manager.mk_and_elim(mp, 1);
|
||||
new_prs.push_back(pr1);
|
||||
new_prs.push_back(pr2);
|
||||
app * q1q2 = m.mk_and(q1,q2);
|
||||
proof * rw = m.mk_oeq_rewrite(new_q, q1q2);
|
||||
proof * mp = m.mk_modus_ponens(new_pr, rw);
|
||||
pr1 = m.mk_and_elim(mp, 0);
|
||||
pr2 = m.mk_and_elim(mp, 1);
|
||||
}
|
||||
new_fmls.push_back(justified_expr(m, q1, pr1));
|
||||
new_fmls.push_back(justified_expr(m, q2, pr2));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -118,7 +185,7 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
|
|||
n is of the form: (forall (X) (iff (= (f X) t) def[X]))
|
||||
|
||||
Convert it into:
|
||||
|
||||
|
||||
(forall (X) (= (f X) (ite def[X] t (k X))))
|
||||
(forall (X) (not (= (k X) t)))
|
||||
|
||||
|
@ -126,13 +193,13 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
|
|||
|
||||
The new quantifiers and proofs are stored in new_exprs and new_prs
|
||||
*/
|
||||
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr,
|
||||
expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr, expr_dependency * dep,
|
||||
expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps ) {
|
||||
func_decl * f = head->get_decl();
|
||||
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
||||
app * ite = m.mk_ite(def, t, k_app);
|
||||
app * body_1 = m.mk_eq(head, ite);
|
||||
app * body_1 = m.mk_eq(head, ite);
|
||||
app * body_2 = m.mk_not(m.mk_eq(k_app, t));
|
||||
quantifier * q1 = m.update_quantifier(q, body_1);
|
||||
expr * pats[1] = { m.mk_pattern(k_app) };
|
||||
|
@ -153,68 +220,158 @@ static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, e
|
|||
new_prs.push_back(pr1);
|
||||
new_prs.push_back(pr2);
|
||||
}
|
||||
new_deps.push_back(dep);
|
||||
new_deps.push_back(dep);
|
||||
}
|
||||
|
||||
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr,
|
||||
vector<justified_expr>& new_fmls) {
|
||||
func_decl * f = head->get_decl();
|
||||
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
||||
app * ite = m.mk_ite(def, t, k_app);
|
||||
app * body_1 = m.mk_eq(head, ite);
|
||||
app * body_2 = m.mk_not(m.mk_eq(k_app, t));
|
||||
quantifier * q1 = m.update_quantifier(q, body_1);
|
||||
proof * pr1 = 0, *pr2 = 0;
|
||||
expr * pats[1] = { m.mk_pattern(k_app) };
|
||||
quantifier * q2 = m.update_quantifier(q, 1, pats, body_2); // erase patterns
|
||||
if (m.proofs_enabled()) {
|
||||
// r : [rewrite] q ~ q1 & q2
|
||||
// pr : q
|
||||
// mp : [modus_pones pr pr1] q1 & q2
|
||||
// pr1 : [and-elim mp] q1
|
||||
// pr2 : [and-elim mp] q2
|
||||
app * q1q2 = m.mk_and(q1,q2);
|
||||
proof * r = m.mk_oeq_rewrite(q, q1q2);
|
||||
proof * mp = m.mk_modus_ponens(pr, r);
|
||||
pr1 = m.mk_and_elim(mp, 0);
|
||||
pr2 = m.mk_and_elim(mp, 1);
|
||||
}
|
||||
new_fmls.push_back(justified_expr(m, q1, pr1));
|
||||
new_fmls.push_back(justified_expr(m, q2, pr2));
|
||||
}
|
||||
|
||||
macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_macro_manager(mm),
|
||||
m_util(mm.get_util()) {
|
||||
m_util(mm.get_util()),
|
||||
m_autil(m) {
|
||||
}
|
||||
|
||||
macro_finder::~macro_finder() {
|
||||
}
|
||||
|
||||
bool macro_finder::expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
bool macro_finder::expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||
TRACE("macro_finder", tout << "starting expand_macros:\n";
|
||||
m_macro_manager.display(tout););
|
||||
bool found_new_macro = false;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * n = exprs[i];
|
||||
proof * pr = m_manager.proofs_enabled() ? prs[i] : 0;
|
||||
expr_ref new_n(m_manager), def(m_manager);
|
||||
proof_ref new_pr(m_manager);
|
||||
m_macro_manager.expand_macros(n, pr, new_n, new_pr);
|
||||
app_ref head(m_manager), t(m_manager);
|
||||
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr)) {
|
||||
proof * pr = m.proofs_enabled() ? prs[i] : 0;
|
||||
expr_dependency * depi = deps != 0 ? deps[i] : 0;
|
||||
expr_ref new_n(m), def(m);
|
||||
proof_ref new_pr(m);
|
||||
expr_dependency_ref new_dep(m);
|
||||
m_macro_manager.expand_macros(n, pr, depi, new_n, new_pr, new_dep);
|
||||
app_ref head(m), t(m);
|
||||
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr, new_dep)) {
|
||||
TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else if (is_arith_macro(new_n, new_pr, new_exprs, new_prs)) {
|
||||
else if (is_arith_macro(new_n, new_pr, new_dep, new_exprs, new_prs, new_deps)) {
|
||||
TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) {
|
||||
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) {
|
||||
TRACE("macro_finder_found", tout << "found new pseudo macro:\n" << head << "\n" << t << "\n" << def << "\n";);
|
||||
pseudo_predicate_macro2macro(m_manager, head, t, def, to_quantifier(new_n), new_pr, new_exprs, new_prs);
|
||||
pseudo_predicate_macro2macro(m, head, t, def, to_quantifier(new_n), new_pr, new_dep, new_exprs, new_prs, new_deps);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else {
|
||||
new_exprs.push_back(new_n);
|
||||
if (m_manager.proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
new_prs.push_back(new_pr);
|
||||
if (deps != 0)
|
||||
new_deps.push_back(new_dep);
|
||||
}
|
||||
}
|
||||
return found_new_macro;
|
||||
}
|
||||
|
||||
void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||
TRACE("macro_finder", tout << "processing macros...\n";);
|
||||
expr_ref_vector _new_exprs(m_manager);
|
||||
proof_ref_vector _new_prs(m_manager);
|
||||
if (expand_macros(num, exprs, prs, _new_exprs, _new_prs)) {
|
||||
expr_ref_vector _new_exprs(m);
|
||||
proof_ref_vector _new_prs(m);
|
||||
expr_dependency_ref_vector _new_deps(m);
|
||||
if (expand_macros(num, exprs, prs, deps, _new_exprs, _new_prs, _new_deps)) {
|
||||
while (true) {
|
||||
expr_ref_vector old_exprs(m_manager);
|
||||
proof_ref_vector old_prs(m_manager);
|
||||
expr_ref_vector old_exprs(m);
|
||||
proof_ref_vector old_prs(m);
|
||||
expr_dependency_ref_vector old_deps(m);
|
||||
_new_exprs.swap(old_exprs);
|
||||
_new_prs.swap(old_prs);
|
||||
_new_deps.swap(old_deps);
|
||||
SASSERT(_new_exprs.empty());
|
||||
SASSERT(_new_prs.empty());
|
||||
if (!expand_macros(old_exprs.size(), old_exprs.c_ptr(), old_prs.c_ptr(), _new_exprs, _new_prs))
|
||||
SASSERT(_new_deps.empty());
|
||||
if (!expand_macros(old_exprs.size(), old_exprs.c_ptr(), old_prs.c_ptr(), old_deps.c_ptr(),
|
||||
_new_exprs, _new_prs, _new_deps))
|
||||
break;
|
||||
}
|
||||
}
|
||||
new_exprs.append(_new_exprs);
|
||||
new_prs.append(_new_prs);
|
||||
new_deps.append(_new_deps);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool macro_finder::expand_macros(unsigned num, justified_expr const * fmls, vector<justified_expr>& new_fmls) {
|
||||
TRACE("macro_finder", tout << "starting expand_macros:\n";
|
||||
m_macro_manager.display(tout););
|
||||
bool found_new_macro = false;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * n = fmls[i].get_fml();
|
||||
proof * pr = m.proofs_enabled() ? fmls[i].get_proof() : 0;
|
||||
expr_ref new_n(m), def(m);
|
||||
proof_ref new_pr(m);
|
||||
expr_dependency_ref new_dep(m);
|
||||
m_macro_manager.expand_macros(n, pr, 0, new_n, new_pr, new_dep);
|
||||
app_ref head(m), t(m);
|
||||
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr)) {
|
||||
TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else if (is_arith_macro(new_n, new_pr, new_fmls)) {
|
||||
TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) {
|
||||
TRACE("macro_finder_found", tout << "found new pseudo macro:\n" << head << "\n" << t << "\n" << def << "\n";);
|
||||
pseudo_predicate_macro2macro(m, head, t, def, to_quantifier(new_n), new_pr, new_fmls);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else {
|
||||
new_fmls.push_back(justified_expr(m, new_n, new_pr));
|
||||
}
|
||||
}
|
||||
return found_new_macro;
|
||||
}
|
||||
|
||||
void macro_finder::operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
TRACE("macro_finder", tout << "processing macros...\n";);
|
||||
vector<justified_expr> _new_fmls;
|
||||
if (expand_macros(n, fmls, _new_fmls)) {
|
||||
while (true) {
|
||||
vector<justified_expr> old_fmls;
|
||||
_new_fmls.swap(old_fmls);
|
||||
SASSERT(_new_fmls.empty());
|
||||
if (!expand_macros(old_fmls.size(), old_fmls.c_ptr(), _new_fmls))
|
||||
break;
|
||||
}
|
||||
}
|
||||
new_fmls.append(_new_fmls);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,36 +19,32 @@ Revision History:
|
|||
#ifndef MACRO_FINDER_H_
|
||||
#define MACRO_FINDER_H_
|
||||
|
||||
#include"macro_manager.h"
|
||||
#include"arith_simplifier_plugin.h"
|
||||
#include "ast/macros/macro_manager.h"
|
||||
|
||||
|
||||
bool is_macro_head(expr * n, unsigned num_decls);
|
||||
bool is_simple_macro(ast_manager & m, expr * n, unsigned num_decls, obj_hashtable<func_decl> const * forbidden_set, app * & head, expr * & def);
|
||||
inline bool is_simple_macro(ast_manager & m, expr * n, unsigned num_decls, app * & head, expr * & def) {
|
||||
return is_simple_macro(m, n, num_decls, 0, head, def);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Macro finder is responsible for finding universally quantified sub-formulas that can be used
|
||||
as macros.
|
||||
*/
|
||||
class macro_finder {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
macro_manager & m_macro_manager;
|
||||
macro_util & m_util;
|
||||
arith_simplifier_plugin * get_arith_simp() { return m_util.get_arith_simp(); }
|
||||
bool expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
arith_util m_autil;
|
||||
bool expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const* deps,
|
||||
expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector& new_deps);
|
||||
bool expand_macros(unsigned n, justified_expr const * fmls, vector<justified_expr>& new_fmls);
|
||||
bool is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
bool is_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls);
|
||||
bool is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||
|
||||
bool is_macro(expr * n, app_ref & head, expr_ref & def);
|
||||
bool is_pseudo_head(expr * n, unsigned num_decls, app * & head, app * & t);
|
||||
bool is_pseudo_predicate_macro(expr * n, app * & head, app * & t, expr * & def);
|
||||
|
||||
public:
|
||||
macro_finder(ast_manager & m, macro_manager & mm);
|
||||
~macro_finder();
|
||||
void operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
void operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const* deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||
void operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
|
||||
};
|
||||
|
||||
#endif /* MACRO_FINDER_H_ */
|
||||
|
|
|
@ -19,19 +19,22 @@ Revision History:
|
|||
Leonardo de Moura (leonardo) 2010-12-15: Moved dependency management to func_decl_dependencies.h
|
||||
|
||||
--*/
|
||||
#include"macro_manager.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"var_subst.h"
|
||||
#include"ast_pp.h"
|
||||
#include"recurse_expr_def.h"
|
||||
#include "ast/macros/macro_manager.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/recurse_expr_def.h"
|
||||
|
||||
macro_manager::macro_manager(ast_manager & m, simplifier & s):
|
||||
m_manager(m),
|
||||
m_simplifier(s),
|
||||
m_util(m, s),
|
||||
|
||||
macro_manager::macro_manager(ast_manager & m):
|
||||
m(m),
|
||||
m_util(m),
|
||||
m_decls(m),
|
||||
m_macros(m),
|
||||
m_macro_prs(m),
|
||||
m_macro_deps(m),
|
||||
m_forbidden(m),
|
||||
m_deps(m) {
|
||||
m_util.set_forbidden_set(&m_forbidden_set);
|
||||
|
@ -60,13 +63,15 @@ void macro_manager::restore_decls(unsigned old_sz) {
|
|||
for (unsigned i = old_sz; i < sz; i++) {
|
||||
m_decl2macro.erase(m_decls.get(i));
|
||||
m_deps.erase(m_decls.get(i));
|
||||
if (m_manager.proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
m_decl2macro_pr.erase(m_decls.get(i));
|
||||
m_decl2macro_dep.erase(m_decls.get(i));
|
||||
}
|
||||
m_decls.shrink(old_sz);
|
||||
m_macros.shrink(old_sz);
|
||||
if (m_manager.proofs_enabled())
|
||||
if (m.proofs_enabled())
|
||||
m_macro_prs.shrink(old_sz);
|
||||
m_macro_deps.shrink(old_sz);
|
||||
}
|
||||
|
||||
void macro_manager::restore_forbidden(unsigned old_sz) {
|
||||
|
@ -79,17 +84,19 @@ void macro_manager::restore_forbidden(unsigned old_sz) {
|
|||
void macro_manager::reset() {
|
||||
m_decl2macro.reset();
|
||||
m_decl2macro_pr.reset();
|
||||
m_decl2macro_dep.reset();
|
||||
m_decls.reset();
|
||||
m_macros.reset();
|
||||
m_macro_prs.reset();
|
||||
m_macro_deps.reset();
|
||||
m_scopes.reset();
|
||||
m_forbidden_set.reset();
|
||||
m_forbidden.reset();
|
||||
m_deps.reset();
|
||||
}
|
||||
|
||||
bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) {
|
||||
TRACE("macro_insert", tout << "trying to create macro: " << f->get_name() << "\n" << mk_pp(m, m_manager) << "\n";);
|
||||
bool macro_manager::insert(func_decl * f, quantifier * q, proof * pr, expr_dependency* dep) {
|
||||
TRACE("macro_insert", tout << "trying to create macro: " << f->get_name() << "\n" << mk_pp(q, m) << "\n";);
|
||||
|
||||
// if we already have a macro for f then return false;
|
||||
if (m_decls.contains(f)) {
|
||||
|
@ -99,7 +106,7 @@ bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) {
|
|||
|
||||
app * head;
|
||||
expr * definition;
|
||||
get_head_def(m, f, head, definition);
|
||||
get_head_def(q, f, head, definition);
|
||||
|
||||
func_decl_set * s = m_deps.mk_func_decl_set();
|
||||
m_deps.collect_func_decls(definition, s);
|
||||
|
@ -108,13 +115,15 @@ bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) {
|
|||
}
|
||||
|
||||
// add macro
|
||||
m_decl2macro.insert(f, m);
|
||||
m_decl2macro.insert(f, q);
|
||||
m_decls.push_back(f);
|
||||
m_macros.push_back(m);
|
||||
if (m_manager.proofs_enabled()) {
|
||||
m_macros.push_back(q);
|
||||
if (m.proofs_enabled()) {
|
||||
m_macro_prs.push_back(pr);
|
||||
m_decl2macro_pr.insert(f, pr);
|
||||
}
|
||||
m_macro_deps.push_back(dep);
|
||||
m_decl2macro_dep.insert(f, dep);
|
||||
|
||||
TRACE("macro_insert", tout << "A macro was successfully created for: " << f->get_name() << "\n";);
|
||||
|
||||
|
@ -150,9 +159,17 @@ void macro_manager::mark_forbidden(unsigned n, expr * const * exprs) {
|
|||
for_each_expr(p, visited, exprs[i]);
|
||||
}
|
||||
|
||||
void macro_manager::mark_forbidden(unsigned n, justified_expr const * exprs) {
|
||||
expr_mark visited;
|
||||
macro_manager_ns::proc p(m_forbidden_set, m_forbidden);
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
for_each_expr(p, visited, exprs[i].get_fml());
|
||||
}
|
||||
|
||||
|
||||
void macro_manager::get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const {
|
||||
app * body = to_app(q->get_expr());
|
||||
SASSERT(m_manager.is_eq(body) || m_manager.is_iff(body));
|
||||
SASSERT(m.is_eq(body) || m.is_iff(body));
|
||||
expr * lhs = to_app(body)->get_arg(0);
|
||||
expr * rhs = to_app(body)->get_arg(1);
|
||||
SASSERT(is_app_of(lhs, d) || is_app_of(rhs, d));
|
||||
|
@ -177,7 +194,7 @@ void macro_manager::display(std::ostream & out) {
|
|||
expr * def;
|
||||
get_head_def(q, f, head, def);
|
||||
SASSERT(q);
|
||||
out << mk_pp(head, m_manager) << " ->\n" << mk_pp(def, m_manager) << "\n";
|
||||
out << mk_pp(head, m) << " ->\n" << mk_pp(def, m) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,132 +205,157 @@ func_decl * macro_manager::get_macro_interpretation(unsigned i, expr_ref & inter
|
|||
expr * def;
|
||||
get_head_def(q, f, head, def);
|
||||
TRACE("macro_bug",
|
||||
tout << f->get_name() << "\n" << mk_pp(head, m_manager) << "\n" << mk_pp(q, m_manager) << "\n";);
|
||||
tout << f->get_name() << "\n" << mk_pp(head, m) << "\n" << mk_pp(q, m) << "\n";);
|
||||
m_util.mk_macro_interpretation(head, q->get_num_decls(), def, interp);
|
||||
return f;
|
||||
}
|
||||
|
||||
macro_manager::macro_expander::macro_expander(ast_manager & m, macro_manager & mm, simplifier & s):
|
||||
simplifier(m),
|
||||
m_macro_manager(mm) {
|
||||
// REMARK: theory simplifier should not be used by macro_expander...
|
||||
// is_arith_macro rewrites a quantifer such as:
|
||||
// forall (x Int) (= (+ x (+ (f x) 1)) 2)
|
||||
// into
|
||||
// forall (x Int) (= (f x) (+ 1 (* -1 x)))
|
||||
// The goal is to make simple macro detection detect the arith macro.
|
||||
// The arith simplifier will undo this transformation.
|
||||
// borrow_plugins(s);
|
||||
enable_ac_support(false);
|
||||
}
|
||||
struct macro_manager::macro_expander_cfg : public default_rewriter_cfg {
|
||||
ast_manager& m;
|
||||
macro_manager& mm;
|
||||
expr_dependency_ref m_used_macro_dependencies;
|
||||
expr_ref_vector m_trail;
|
||||
|
||||
macro_manager::macro_expander::~macro_expander() {
|
||||
// release_plugins();
|
||||
}
|
||||
macro_expander_cfg(ast_manager& m, macro_manager& mm):
|
||||
m(m),
|
||||
mm(mm),
|
||||
m_used_macro_dependencies(m),
|
||||
m_trail(m)
|
||||
{}
|
||||
|
||||
void macro_manager::macro_expander::reduce1_quantifier(quantifier * q) {
|
||||
simplifier::reduce1_quantifier(q);
|
||||
// If a macro was expanded in a pattern, we must erase it since it may not be a valid pattern anymore.
|
||||
// The MAM assumes valid patterns, and it crashes if invalid patterns are provided.
|
||||
// For example, it will crash if the pattern does not contain all variables.
|
||||
//
|
||||
// Alternative solution: use pattern_validation to check if the pattern is still valid.
|
||||
// I'm not sure if this is a good solution, since the pattern may be meaningless after the macro expansion.
|
||||
// So, I'm just erasing them.
|
||||
expr * new_q_expr = 0;
|
||||
proof * new_q_pr = 0;
|
||||
get_cached(q, new_q_expr, new_q_pr);
|
||||
if (!is_quantifier(new_q_expr))
|
||||
return;
|
||||
quantifier * new_q = to_quantifier(new_q_expr);
|
||||
bool erase_patterns = false;
|
||||
if (q->get_num_patterns() != new_q->get_num_patterns() ||
|
||||
q->get_num_no_patterns() != new_q->get_num_no_patterns()) {
|
||||
erase_patterns = true;
|
||||
bool rewrite_patterns() const { return false; }
|
||||
bool flat_assoc(func_decl * f) const { return false; }
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
result_pr = 0;
|
||||
return BR_FAILED;
|
||||
}
|
||||
else {
|
||||
for (unsigned i = 0; !erase_patterns && i < q->get_num_patterns(); i++) {
|
||||
if (q->get_pattern(i) != new_q->get_pattern(i))
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
||||
// If a macro was expanded in a pattern, we must erase it since it may not be a valid pattern anymore.
|
||||
// The MAM assumes valid patterns, and it crashes if invalid patterns are provided.
|
||||
// For example, it will crash if the pattern does not contain all variables.
|
||||
//
|
||||
// Alternative solution: use pattern_validation to check if the pattern is still valid.
|
||||
// I'm not sure if this is a good solution, since the pattern may be meaningless after the macro expansion.
|
||||
// So, I'm just erasing them.
|
||||
|
||||
bool erase_patterns = false;
|
||||
for (unsigned i = 0; !erase_patterns && i < old_q->get_num_patterns(); i++) {
|
||||
if (old_q->get_pattern(i) != new_patterns[i])
|
||||
erase_patterns = true;
|
||||
}
|
||||
for (unsigned i = 0; !erase_patterns && i < q->get_num_no_patterns(); i++) {
|
||||
if (q->get_no_pattern(i) != new_q->get_no_pattern(i))
|
||||
for (unsigned i = 0; !erase_patterns && i < old_q->get_num_no_patterns(); i++) {
|
||||
if (old_q->get_no_pattern(i) != new_no_patterns[i])
|
||||
erase_patterns = true;
|
||||
}
|
||||
if (erase_patterns) {
|
||||
result = m.update_quantifier(old_q, 0, 0, 0, 0, new_body);
|
||||
}
|
||||
return erase_patterns;
|
||||
}
|
||||
if (erase_patterns) {
|
||||
ast_manager & m = get_manager();
|
||||
expr * new_new_q = m.update_quantifier(new_q, 0, 0, 0, 0, new_q->get_expr());
|
||||
// we can use the same proof since new_new_q and new_q are identical modulo patterns/annotations
|
||||
cache_result(q, new_new_q, new_q_pr);
|
||||
}
|
||||
}
|
||||
|
||||
bool macro_manager::macro_expander::get_subst(expr * _n, expr_ref & r, proof_ref & p) {
|
||||
if (!is_app(_n))
|
||||
bool get_subst(expr * _n, expr* & r, proof* & p) {
|
||||
if (!is_app(_n))
|
||||
return false;
|
||||
app * n = to_app(_n);
|
||||
quantifier * q = 0;
|
||||
func_decl * d = n->get_decl();
|
||||
TRACE("macro_manager", tout << "trying to expand:\n" << mk_pp(n, m) << "\nd:\n" << d->get_name() << "\n";);
|
||||
if (mm.m_decl2macro.find(d, q)) {
|
||||
TRACE("macro_manager", tout << "expanding: " << mk_pp(n, m) << "\n";);
|
||||
app * head = 0;
|
||||
expr * def = 0;
|
||||
mm.get_head_def(q, d, head, def);
|
||||
unsigned num = n->get_num_args();
|
||||
SASSERT(head && def);
|
||||
ptr_buffer<expr> subst_args;
|
||||
subst_args.resize(num, 0);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
var * v = to_var(head->get_arg(i));
|
||||
SASSERT(v->get_idx() < num);
|
||||
unsigned nidx = num - v->get_idx() - 1;
|
||||
SASSERT(subst_args[nidx] == 0);
|
||||
subst_args[nidx] = n->get_arg(i);
|
||||
}
|
||||
var_subst s(m);
|
||||
expr_ref rr(m);
|
||||
s(def, num, subst_args.c_ptr(), rr);
|
||||
m_trail.push_back(rr);
|
||||
r = rr;
|
||||
if (m.proofs_enabled()) {
|
||||
expr_ref instance(m);
|
||||
s(q->get_expr(), num, subst_args.c_ptr(), instance);
|
||||
proof * qi_pr = m.mk_quant_inst(m.mk_or(m.mk_not(q), instance), num, subst_args.c_ptr());
|
||||
proof * q_pr = 0;
|
||||
mm.m_decl2macro_pr.find(d, q_pr);
|
||||
SASSERT(q_pr != 0);
|
||||
proof * prs[2] = { qi_pr, q_pr };
|
||||
p = m.mk_unit_resolution(2, prs);
|
||||
}
|
||||
else {
|
||||
p = 0;
|
||||
}
|
||||
expr_dependency * ed = mm.m_decl2macro_dep.find(d);
|
||||
m_used_macro_dependencies = m.mk_join(m_used_macro_dependencies, ed);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
app * n = to_app(_n);
|
||||
quantifier * q = 0;
|
||||
func_decl * d = n->get_decl();
|
||||
TRACE("macro_manager_bug", tout << "trying to expand:\n" << mk_pp(n, m) << "\nd:\n" << d->get_name() << "\n";);
|
||||
if (m_macro_manager.m_decl2macro.find(d, q)) {
|
||||
TRACE("macro_manager", tout << "expanding: " << mk_pp(n, m) << "\n";);
|
||||
app * head = 0;
|
||||
expr * def = 0;
|
||||
m_macro_manager.get_head_def(q, d, head, def);
|
||||
unsigned num = n->get_num_args();
|
||||
SASSERT(head && def);
|
||||
ptr_buffer<expr> subst_args;
|
||||
subst_args.resize(num, 0);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
var * v = to_var(head->get_arg(i));
|
||||
SASSERT(v->get_idx() < num);
|
||||
unsigned nidx = num - v->get_idx() - 1;
|
||||
SASSERT(subst_args[nidx] == 0);
|
||||
subst_args[nidx] = n->get_arg(i);
|
||||
}
|
||||
var_subst s(m);
|
||||
s(def, num, subst_args.c_ptr(), r);
|
||||
if (m.proofs_enabled()) {
|
||||
expr_ref instance(m);
|
||||
s(q->get_expr(), num, subst_args.c_ptr(), instance);
|
||||
proof * qi_pr = m.mk_quant_inst(m.mk_or(m.mk_not(q), instance), num, subst_args.c_ptr());
|
||||
proof * q_pr = 0;
|
||||
m_macro_manager.m_decl2macro_pr.find(d, q_pr);
|
||||
SASSERT(q_pr != 0);
|
||||
proof * prs[2] = { qi_pr, q_pr };
|
||||
p = m.mk_unit_resolution(2, prs);
|
||||
}
|
||||
else {
|
||||
p = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void macro_manager::expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref & new_pr) {
|
||||
struct macro_manager::macro_expander_rw : public rewriter_tpl<macro_manager::macro_expander_cfg> {
|
||||
macro_expander_cfg m_cfg;
|
||||
|
||||
macro_expander_rw(ast_manager& m, macro_manager& mm):
|
||||
rewriter_tpl<macro_manager::macro_expander_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||
m_cfg(m, mm)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
void macro_manager::expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep) {
|
||||
if (has_macros()) {
|
||||
// Expand macros with "real" proof production support (NO rewrite*)
|
||||
expr_ref old_n(m_manager);
|
||||
proof_ref old_pr(m_manager);
|
||||
expr_ref old_n(m);
|
||||
proof_ref old_pr(m);
|
||||
expr_dependency_ref old_dep(m);
|
||||
old_n = n;
|
||||
old_pr = pr;
|
||||
old_dep = dep;
|
||||
bool change = false;
|
||||
for (;;) {
|
||||
macro_expander proc(m_manager, *this, m_simplifier);
|
||||
proof_ref n_eq_r_pr(m_manager);
|
||||
TRACE("macro_manager_bug", tout << "expand_macros:\n" << mk_pp(n, m_manager) << "\n";);
|
||||
macro_expander_rw proc(m, *this);
|
||||
proof_ref n_eq_r_pr(m);
|
||||
TRACE("macro_manager_bug", tout << "expand_macros:\n" << mk_pp(n, m) << "\n";);
|
||||
proc(old_n, r, n_eq_r_pr);
|
||||
new_pr = m_manager.mk_modus_ponens(old_pr, n_eq_r_pr);
|
||||
new_pr = m.mk_modus_ponens(old_pr, n_eq_r_pr);
|
||||
new_dep = m.mk_join(old_dep, proc.m_cfg.m_used_macro_dependencies);
|
||||
if (r.get() == old_n.get())
|
||||
return;
|
||||
break;
|
||||
old_n = r;
|
||||
old_pr = new_pr;
|
||||
old_dep = new_dep;
|
||||
change = true;
|
||||
}
|
||||
// apply th_rewrite to the result.
|
||||
if (change) {
|
||||
th_rewriter rw(m);
|
||||
proof_ref rw_pr(m);
|
||||
expr_ref r1(r, m);
|
||||
rw(r1, r, rw_pr);
|
||||
new_pr = m.mk_modus_ponens(new_pr, rw_pr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = n;
|
||||
new_pr = pr;
|
||||
new_dep = dep;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ Revision History:
|
|||
#ifndef MACRO_MANAGER_H_
|
||||
#define MACRO_MANAGER_H_
|
||||
|
||||
#include"ast_util.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"simplifier.h"
|
||||
#include"recurse_expr.h"
|
||||
#include"func_decl_dependencies.h"
|
||||
#include"macro_util.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/justified_expr.h"
|
||||
#include "ast/recurse_expr.h"
|
||||
#include "ast/func_decl_dependencies.h"
|
||||
#include "ast/macros/macro_util.h"
|
||||
|
||||
/**
|
||||
\brief Macros are universally quantified formulas of the form:
|
||||
|
@ -36,15 +36,16 @@ Revision History:
|
|||
It has support for backtracking and tagging declarations in an expression as forbidded for being macros.
|
||||
*/
|
||||
class macro_manager {
|
||||
ast_manager & m_manager;
|
||||
simplifier & m_simplifier;
|
||||
ast_manager & m;
|
||||
macro_util m_util;
|
||||
|
||||
obj_map<func_decl, quantifier *> m_decl2macro; // func-decl -> quantifier
|
||||
obj_map<func_decl, proof *> m_decl2macro_pr; // func-decl -> quantifier_proof
|
||||
obj_map<func_decl, expr_dependency *> m_decl2macro_dep; // func-decl -> unsat core dependency
|
||||
func_decl_ref_vector m_decls;
|
||||
quantifier_ref_vector m_macros;
|
||||
proof_ref_vector m_macro_prs;
|
||||
expr_dependency_ref_vector m_macro_deps;
|
||||
obj_hashtable<func_decl> m_forbidden_set;
|
||||
func_decl_ref_vector m_forbidden;
|
||||
struct scope {
|
||||
|
@ -52,34 +53,27 @@ class macro_manager {
|
|||
unsigned m_forbidden_lim;
|
||||
};
|
||||
svector<scope> m_scopes;
|
||||
|
||||
|
||||
func_decl_dependencies m_deps;
|
||||
|
||||
void restore_decls(unsigned old_sz);
|
||||
void restore_forbidden(unsigned old_sz);
|
||||
|
||||
class macro_expander : public simplifier {
|
||||
protected:
|
||||
macro_manager & m_macro_manager;
|
||||
virtual bool get_subst(expr * n, expr_ref & r, proof_ref & p);
|
||||
virtual void reduce1_quantifier(quantifier * q);
|
||||
public:
|
||||
macro_expander(ast_manager & m, macro_manager & mm, simplifier & s);
|
||||
~macro_expander();
|
||||
};
|
||||
friend class macro_expander;
|
||||
struct macro_expander_cfg;
|
||||
struct macro_expander_rw;
|
||||
|
||||
public:
|
||||
macro_manager(ast_manager & m, simplifier & s);
|
||||
macro_manager(ast_manager & m);
|
||||
~macro_manager();
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
ast_manager & get_manager() const { return m; }
|
||||
macro_util & get_util() { return m_util; }
|
||||
bool insert(func_decl * f, quantifier * m, proof * pr);
|
||||
bool insert(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep = 0);
|
||||
bool has_macros() const { return !m_macros.empty(); }
|
||||
void push_scope();
|
||||
void pop_scope(unsigned num_scopes);
|
||||
void reset();
|
||||
void mark_forbidden(unsigned n, expr * const * exprs);
|
||||
void mark_forbidden(unsigned n, justified_expr const * exprs);
|
||||
void mark_forbidden(expr * e) { mark_forbidden(1, &e); }
|
||||
bool is_forbidden(func_decl * d) const { return m_forbidden_set.contains(d); }
|
||||
obj_hashtable<func_decl> const & get_forbidden_set() const { return m_forbidden_set; }
|
||||
|
@ -90,9 +84,9 @@ public:
|
|||
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const;
|
||||
quantifier * get_macro_quantifier(func_decl * f) const { quantifier * q = 0; m_decl2macro.find(f, q); return q; }
|
||||
void get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const;
|
||||
void expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref & new_pr);
|
||||
|
||||
|
||||
void expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* MACRO_MANAGER_H_ */
|
||||
|
|
|
@ -17,44 +17,26 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"macro_util.h"
|
||||
#include"occurs.h"
|
||||
#include"ast_util.h"
|
||||
#include"arith_simplifier_plugin.h"
|
||||
#include"bv_simplifier_plugin.h"
|
||||
#include"var_subst.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"well_sorted.h"
|
||||
#include"bool_rewriter.h"
|
||||
#include "ast/macros/macro_util.h"
|
||||
#include "ast/occurs.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
|
||||
macro_util::macro_util(ast_manager & m, simplifier & s):
|
||||
macro_util::macro_util(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_bv(m),
|
||||
m_simplifier(s),
|
||||
m_arith_simp(0),
|
||||
m_bv_simp(0),
|
||||
m_arith(m),
|
||||
m_arith_rw(m),
|
||||
m_bv_rw(m),
|
||||
m_forbidden_set(0),
|
||||
m_curr_clause(0) {
|
||||
}
|
||||
|
||||
arith_simplifier_plugin * macro_util::get_arith_simp() const {
|
||||
if (m_arith_simp == 0) {
|
||||
const_cast<macro_util*>(this)->m_arith_simp = static_cast<arith_simplifier_plugin*>(m_simplifier.get_plugin(m_manager.mk_family_id("arith")));
|
||||
}
|
||||
SASSERT(m_arith_simp != 0);
|
||||
return m_arith_simp;
|
||||
}
|
||||
|
||||
bv_simplifier_plugin * macro_util::get_bv_simp() const {
|
||||
if (m_bv_simp == 0) {
|
||||
const_cast<macro_util*>(this)->m_bv_simp = static_cast<bv_simplifier_plugin*>(m_simplifier.get_plugin(m_manager.mk_family_id("bv")));
|
||||
}
|
||||
SASSERT(m_bv_simp != 0);
|
||||
return m_bv_simp;
|
||||
}
|
||||
|
||||
|
||||
bool macro_util::is_bv(expr * n) const {
|
||||
return m_bv.is_bv(n);
|
||||
|
@ -65,60 +47,83 @@ bool macro_util::is_bv_sort(sort * s) const {
|
|||
}
|
||||
|
||||
bool macro_util::is_add(expr * n) const {
|
||||
return get_arith_simp()->is_add(n) || m_bv.is_bv_add(n);
|
||||
return m_arith.is_add(n) || m_bv.is_bv_add(n);
|
||||
}
|
||||
|
||||
bool macro_util::is_times_minus_one(expr * n, expr * & arg) const {
|
||||
return get_arith_simp()->is_times_minus_one(n, arg) || get_bv_simp()->is_times_minus_one(n, arg);
|
||||
return m_arith_rw.is_times_minus_one(n, arg) || m_bv_rw.is_times_minus_one(n, arg);
|
||||
}
|
||||
|
||||
bool macro_util::is_le(expr * n) const {
|
||||
return get_arith_simp()->is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
|
||||
return m_arith.is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
|
||||
}
|
||||
|
||||
bool macro_util::is_le_ge(expr * n) const {
|
||||
return get_arith_simp()->is_le_ge(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
|
||||
return m_arith.is_ge(n) || m_arith.is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
|
||||
}
|
||||
|
||||
poly_simplifier_plugin * macro_util::get_poly_simp_for(sort * s) const {
|
||||
if (is_bv_sort(s))
|
||||
return get_bv_simp();
|
||||
else
|
||||
return get_arith_simp();
|
||||
bool macro_util::is_var_plus_ground(expr * n, bool & inv, var * & v, expr_ref & t) {
|
||||
return m_arith_rw.is_var_plus_ground(n, inv, v, t) || m_bv_rw.is_var_plus_ground(n, inv, v, t);
|
||||
}
|
||||
|
||||
bool macro_util::is_zero_safe(expr * n) const {
|
||||
if (m_bv_rw.is_bv(n)) {
|
||||
return m_bv.is_zero(n);
|
||||
}
|
||||
else {
|
||||
return m_arith_rw.is_zero(n);
|
||||
}
|
||||
}
|
||||
|
||||
app * macro_util::mk_zero(sort * s) const {
|
||||
poly_simplifier_plugin * ps = get_poly_simp_for(s);
|
||||
ps->set_curr_sort(s);
|
||||
return ps->mk_zero();
|
||||
if (m_bv.is_bv_sort(s)) {
|
||||
return m_bv.mk_numeral(rational(0), s);
|
||||
}
|
||||
else {
|
||||
return m_arith.mk_numeral(rational(0), s);
|
||||
}
|
||||
}
|
||||
|
||||
void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
|
||||
if (is_bv(t1)) {
|
||||
r = m_bv.mk_bv_sub(t1, t2);
|
||||
m_bv_rw.mk_sub(t1, t2, r);
|
||||
}
|
||||
else {
|
||||
get_arith_simp()->mk_sub(t1, t2, r);
|
||||
m_arith_rw.mk_sub(t1, t2, r);
|
||||
}
|
||||
}
|
||||
|
||||
void macro_util::mk_add(expr * t1, expr * t2, expr_ref & r) const {
|
||||
if (is_bv(t1)) {
|
||||
r = m_bv.mk_bv_add(t1, t2);
|
||||
m_bv_rw.mk_add(t1, t2, r);
|
||||
}
|
||||
else {
|
||||
get_arith_simp()->mk_add(t1, t2, r);
|
||||
m_arith_rw.mk_add(t1, t2, r);
|
||||
}
|
||||
}
|
||||
|
||||
void macro_util::mk_add(unsigned num_args, expr * const * args, sort * s, expr_ref & r) const {
|
||||
if (num_args == 0) {
|
||||
switch (num_args) {
|
||||
case 0:
|
||||
r = mk_zero(s);
|
||||
return;
|
||||
break;
|
||||
case 1:
|
||||
r = args[0];
|
||||
break;
|
||||
default:
|
||||
if (m_bv.is_bv_sort(s)) {
|
||||
r = args[0];
|
||||
while (num_args >= 2) {
|
||||
--num_args;
|
||||
++args;
|
||||
r = m_bv.mk_bv_add(r, args[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = m_arith.mk_add(num_args, args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
poly_simplifier_plugin * ps = get_poly_simp_for(s);
|
||||
ps->set_curr_sort(s);
|
||||
ps->mk_add(num_args, args, r);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,13 +246,12 @@ bool macro_util::poly_contains_head(expr * n, func_decl * f, expr * exception) c
|
|||
|
||||
bool macro_util::is_arith_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def, bool & inv) const {
|
||||
// TODO: obsolete... we should move to collect_arith_macro_candidates
|
||||
arith_simplifier_plugin * as = get_arith_simp();
|
||||
if (!m_manager.is_eq(n) && !as->is_le(n) && !as->is_ge(n))
|
||||
if (!m_manager.is_eq(n) && !m_arith.is_le(n) && !m_arith.is_ge(n))
|
||||
return false;
|
||||
expr * lhs = to_app(n)->get_arg(0);
|
||||
expr * rhs = to_app(n)->get_arg(1);
|
||||
|
||||
if (!as->is_numeral(rhs))
|
||||
if (!m_arith.is_numeral(rhs))
|
||||
return false;
|
||||
|
||||
inv = false;
|
||||
|
@ -272,7 +276,7 @@ bool macro_util::is_arith_macro(expr * n, unsigned num_decls, app_ref & head, ex
|
|||
!poly_contains_head(lhs, to_app(arg)->get_decl(), arg)) {
|
||||
h = arg;
|
||||
}
|
||||
else if (h == 0 && as->is_times_minus_one(arg, neg_arg) &&
|
||||
else if (h == 0 && m_arith_rw.is_times_minus_one(arg, neg_arg) &&
|
||||
is_macro_head(neg_arg, num_decls) &&
|
||||
!is_forbidden(to_app(neg_arg)->get_decl()) &&
|
||||
!poly_contains_head(lhs, to_app(neg_arg)->get_decl(), arg)) {
|
||||
|
@ -287,11 +291,12 @@ bool macro_util::is_arith_macro(expr * n, unsigned num_decls, app_ref & head, ex
|
|||
return false;
|
||||
head = to_app(h);
|
||||
expr_ref tmp(m_manager);
|
||||
as->mk_add(args.size(), args.c_ptr(), tmp);
|
||||
tmp = m_arith.mk_add(args.size(), args.c_ptr());
|
||||
if (inv)
|
||||
as->mk_sub(tmp, rhs, def);
|
||||
mk_sub(tmp, rhs, def);
|
||||
else
|
||||
as->mk_sub(rhs, tmp, def);
|
||||
mk_sub(rhs, tmp, def);
|
||||
TRACE("macro_util", tout << def << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,10 @@ Revision History:
|
|||
#ifndef MACRO_UTIL_H_
|
||||
#define MACRO_UTIL_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"simplifier.h"
|
||||
|
||||
class poly_simplifier_plugin;
|
||||
class arith_simplifier_plugin;
|
||||
class bv_simplifier_plugin;
|
||||
class basic_simplifier_plugin;
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/rewriter/arith_rewriter.h"
|
||||
#include "ast/rewriter/bv_rewriter.h"
|
||||
|
||||
class macro_util {
|
||||
public:
|
||||
|
@ -63,9 +59,9 @@ public:
|
|||
private:
|
||||
ast_manager & m_manager;
|
||||
bv_util m_bv;
|
||||
simplifier & m_simplifier;
|
||||
arith_simplifier_plugin * m_arith_simp;
|
||||
bv_simplifier_plugin * m_bv_simp;
|
||||
arith_util m_arith;
|
||||
mutable arith_rewriter m_arith_rw;
|
||||
mutable bv_rewriter m_bv_rw;
|
||||
obj_hashtable<func_decl> * m_forbidden_set;
|
||||
|
||||
bool is_forbidden(func_decl * f) const { return m_forbidden_set != 0 && m_forbidden_set->contains(f); }
|
||||
|
@ -94,11 +90,9 @@ private:
|
|||
|
||||
|
||||
public:
|
||||
macro_util(ast_manager & m, simplifier & s);
|
||||
macro_util(ast_manager & m);
|
||||
void set_forbidden_set(obj_hashtable<func_decl> * s) { m_forbidden_set = s; }
|
||||
|
||||
arith_simplifier_plugin * get_arith_simp() const;
|
||||
bv_simplifier_plugin * get_bv_simp() const;
|
||||
|
||||
bool is_macro_head(expr * n, unsigned num_decls) const;
|
||||
bool is_left_simple_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def) const;
|
||||
|
@ -113,6 +107,8 @@ public:
|
|||
return is_arith_macro(n, num_decls, head, def, inv);
|
||||
}
|
||||
|
||||
bool is_zero_safe(expr * n) const;
|
||||
bool is_var_plus_ground(expr * n, bool & inv, var * & v, expr_ref & t);
|
||||
bool is_pseudo_head(expr * n, unsigned num_decls, app_ref & head, app_ref & t);
|
||||
bool is_pseudo_predicate_macro(expr * n, app_ref & head, app_ref & t, expr_ref & def);
|
||||
|
||||
|
@ -137,7 +133,6 @@ public:
|
|||
void mk_sub(expr * t1, expr * t2, expr_ref & r) const;
|
||||
void mk_add(expr * t1, expr * t2, expr_ref & r) const;
|
||||
void mk_add(unsigned num_args, expr * const * args, sort * s, expr_ref & r) const;
|
||||
poly_simplifier_plugin * get_poly_simp_for(sort * s) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,22 +16,22 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"quasi_macros.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"ast_pp.h"
|
||||
#include"uint_set.h"
|
||||
#include"var_subst.h"
|
||||
#include "ast/macros/quasi_macros.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "util/uint_set.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s) :
|
||||
m_manager(m),
|
||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm) :
|
||||
m_manager(m),
|
||||
m_macro_manager(mm),
|
||||
m_simplifier(s),
|
||||
m_rewriter(m),
|
||||
m_new_vars(m),
|
||||
m_new_eqs(m),
|
||||
m_new_qsorts(m) {
|
||||
}
|
||||
|
||||
quasi_macros::~quasi_macros() {
|
||||
quasi_macros::~quasi_macros() {
|
||||
}
|
||||
|
||||
void quasi_macros::find_occurrences(expr * e) {
|
||||
|
@ -41,7 +41,7 @@ void quasi_macros::find_occurrences(expr * e) {
|
|||
|
||||
// we remember whether we have seen an expr once, or more than once;
|
||||
// when we see it the second time, we don't have to visit it another time,
|
||||
// as we are only interested in finding unique function applications.
|
||||
// as we are only interested in finding unique function applications.
|
||||
m_visited_once.reset();
|
||||
m_visited_more.reset();
|
||||
|
||||
|
@ -64,8 +64,8 @@ void quasi_macros::find_occurrences(expr * e) {
|
|||
if (is_non_ground_uninterp(cur)) {
|
||||
func_decl * f = to_app(cur)->get_decl();
|
||||
m_occurrences.insert_if_not_there(f, 0);
|
||||
occurrences_map::iterator it = m_occurrences.find_iterator(f);
|
||||
it->m_value++;
|
||||
occurrences_map::iterator it = m_occurrences.find_iterator(f);
|
||||
it->m_value++;
|
||||
}
|
||||
j = to_app(cur)->get_num_args();
|
||||
while (j)
|
||||
|
@ -84,16 +84,16 @@ bool quasi_macros::is_unique(func_decl * f) const {
|
|||
return m_occurrences.find(f) == 1;
|
||||
}
|
||||
|
||||
struct var_dep_proc {
|
||||
struct var_dep_proc {
|
||||
bit_vector m_bitset;
|
||||
public:
|
||||
var_dep_proc(quantifier * q) { m_bitset.resize(q->get_num_decls(), false); }
|
||||
void operator()(var * n) { m_bitset.set(n->get_idx(), true); }
|
||||
void operator()(quantifier * n) {}
|
||||
void operator()(app * n) {}
|
||||
bool all_used(void) {
|
||||
bool all_used(void) {
|
||||
for (unsigned i = 0; i < m_bitset.size() ; i++)
|
||||
if (!m_bitset.get(i))
|
||||
if (!m_bitset.get(i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ public:
|
|||
|
||||
bool quasi_macros::fully_depends_on(app * a, quantifier * q) const {
|
||||
// CMW: This checks whether all variables in q are used _somewhere_ deep down in the children of a
|
||||
|
||||
|
||||
/* var_dep_proc proc(q);
|
||||
for_each_expr(proc, a);
|
||||
return proc.all_used(); */
|
||||
|
@ -116,14 +116,14 @@ bool quasi_macros::fully_depends_on(app * a, quantifier * q) const {
|
|||
}
|
||||
|
||||
for (unsigned i = 0; i < bitset.size() ; i++) {
|
||||
if (!bitset.get(i))
|
||||
if (!bitset.get(i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
||||
bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
||||
ptr_vector<expr> todo;
|
||||
expr_mark visited;
|
||||
todo.push_back(e);
|
||||
|
@ -133,12 +133,12 @@ bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
|||
|
||||
if (visited.is_marked(cur))
|
||||
continue;
|
||||
|
||||
|
||||
if (is_app(cur)) {
|
||||
app * a = to_app(cur);
|
||||
if (a->get_decl() == f)
|
||||
if (a->get_decl() == f)
|
||||
return true;
|
||||
|
||||
|
||||
unsigned j = a->get_num_args();
|
||||
while (j>0)
|
||||
todo.push_back(a->get_arg(--j));
|
||||
|
@ -151,7 +151,7 @@ bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
|||
|
||||
bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
||||
// Our definition of a quasi-macro:
|
||||
// Forall X. f[X] = T[X], where f[X] is a term starting with symbol f, f is uninterpreted,
|
||||
// Forall X. f[X] = T[X], where f[X] is a term starting with symbol f, f is uninterpreted,
|
||||
// f[X] contains all universally quantified variables, and f does not occur in T[X].
|
||||
TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
|
||||
|
||||
|
@ -165,14 +165,14 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
|||
if (is_non_ground_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) &&
|
||||
!depends_on(rhs, to_app(lhs)->get_decl()) && fully_depends_on(to_app(lhs), q)) {
|
||||
a = to_app(lhs);
|
||||
t = rhs;
|
||||
t = rhs;
|
||||
return true;
|
||||
} else if (is_non_ground_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) &&
|
||||
!depends_on(lhs, to_app(rhs)->get_decl()) && fully_depends_on(to_app(rhs), q)) {
|
||||
!depends_on(lhs, to_app(rhs)->get_decl()) && fully_depends_on(to_app(rhs), q)) {
|
||||
a = to_app(rhs);
|
||||
t = lhs;
|
||||
t = lhs;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (m_manager.is_not(qe) && is_non_ground_uninterp(to_app(qe)->get_arg(0)) &&
|
||||
is_unique(to_app(to_app(qe)->get_arg(0))->get_decl())) { // this is like f(...) = false
|
||||
a = to_app(to_app(qe)->get_arg(0));
|
||||
|
@ -189,7 +189,7 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
|||
}
|
||||
|
||||
void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quantifier_ref & macro) {
|
||||
m_new_var_names.reset();
|
||||
m_new_var_names.reset();
|
||||
m_new_vars.reset();
|
||||
m_new_qsorts.reset();
|
||||
m_new_eqs.reset();
|
||||
|
@ -197,19 +197,19 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
|||
func_decl * f = a->get_decl();
|
||||
|
||||
// CMW: we rely on the fact that all variables in q appear at least once as
|
||||
// a direct argument of `a'.
|
||||
// a direct argument of `a'.
|
||||
|
||||
bit_vector v_seen;
|
||||
v_seen.resize(q->get_num_decls(), false);
|
||||
v_seen.resize(q->get_num_decls(), false);
|
||||
for (unsigned i = 0 ; i < a->get_num_args() ; i++) {
|
||||
if (!is_var(a->get_arg(i)) ||
|
||||
if (!is_var(a->get_arg(i)) ||
|
||||
v_seen.get(to_var(a->get_arg(i))->get_idx())) {
|
||||
unsigned inx = m_new_var_names.size();
|
||||
m_new_name.str("");
|
||||
m_new_name << "X" << inx;
|
||||
m_new_var_names.push_back(symbol(m_new_name.str().c_str()));
|
||||
m_new_var_names.push_back(symbol(m_new_name.str().c_str()));
|
||||
m_new_qsorts.push_back(f->get_domain()[i]);
|
||||
|
||||
|
||||
m_new_vars.push_back(m_manager.mk_var(inx + q->get_num_decls(), f->get_domain()[i]));
|
||||
m_new_eqs.push_back(m_manager.mk_eq(m_new_vars.back(), a->get_arg(i)));
|
||||
} else {
|
||||
|
@ -228,13 +228,13 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
|||
new_var_names_rev.push_back(m_new_var_names.get(i));
|
||||
new_qsorts_rev.push_back(m_new_qsorts.get(i));
|
||||
}
|
||||
|
||||
|
||||
// We want to keep all the old variables [already reversed]
|
||||
for (unsigned i = 0 ; i < q->get_num_decls() ; i++) {
|
||||
new_var_names_rev.push_back(q->get_decl_name(i));
|
||||
new_qsorts_rev.push_back(q->get_decl_sort(i));
|
||||
}
|
||||
|
||||
|
||||
// Macro := Forall m_new_vars . appl = ITE( m_new_eqs, t, f_else)
|
||||
|
||||
app_ref appl(m_manager);
|
||||
|
@ -251,21 +251,59 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
|||
|
||||
eq = m_manager.mk_eq(appl, ite);
|
||||
|
||||
macro = m_manager.mk_quantifier(true, new_var_names_rev.size(),
|
||||
macro = m_manager.mk_quantifier(true, new_var_names_rev.size(),
|
||||
new_qsorts_rev.c_ptr(), new_var_names_rev.c_ptr(), eq);
|
||||
}
|
||||
|
||||
bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
||||
TRACE("quasi_macros", tout << "Finding quasi-macros in: " << std::endl;
|
||||
for (unsigned i = 0 ; i < n ; i++)
|
||||
for (unsigned i = 0 ; i < n ; i++)
|
||||
tout << i << ": " << mk_pp(exprs[i], m_manager) << std::endl; );
|
||||
bool res = false;
|
||||
m_occurrences.reset();
|
||||
|
||||
|
||||
// Find out how many non-ground appearences for each uninterpreted function there are
|
||||
for (unsigned i = 0 ; i < n ; i++)
|
||||
find_occurrences(exprs[i]);
|
||||
|
||||
TRACE("quasi_macros",
|
||||
tout << "Occurrences: " << std::endl;
|
||||
for (auto & kd : m_occurrences)
|
||||
tout << kd.m_key->get_name() << ": " << kd.m_value << std::endl; );
|
||||
|
||||
// Find all macros
|
||||
for (unsigned i = 0 ; i < n ; i++) {
|
||||
app_ref a(m_manager);
|
||||
expr_ref t(m_manager);
|
||||
if (is_quasi_macro(exprs[i], a, t)) {
|
||||
quantifier_ref macro(m_manager);
|
||||
quasi_macro_to_macro(to_quantifier(exprs[i]), a, t, macro);
|
||||
TRACE("quasi_macros", tout << "Found quasi macro: " << mk_pp(exprs[i], m_manager) << std::endl;
|
||||
tout << "Macro: " << mk_pp(macro, m_manager) << std::endl; );
|
||||
proof * pr = 0;
|
||||
if (m_manager.proofs_enabled())
|
||||
pr = m_manager.mk_def_axiom(macro);
|
||||
expr_dependency * dep = 0;
|
||||
if (m_macro_manager.insert(a->get_decl(), macro, pr, dep))
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool quasi_macros::find_macros(unsigned n, justified_expr const * exprs) {
|
||||
TRACE("quasi_macros", tout << "Finding quasi-macros in: " << std::endl;
|
||||
for (unsigned i = 0 ; i < n ; i++)
|
||||
tout << i << ": " << mk_pp(exprs[i].get_fml(), m_manager) << std::endl; );
|
||||
bool res = false;
|
||||
m_occurrences.reset();
|
||||
|
||||
|
||||
// Find out how many non-ground appearences for each uninterpreted function there are
|
||||
for ( unsigned i = 0 ; i < n ; i++ )
|
||||
find_occurrences(exprs[i]);
|
||||
find_occurrences(exprs[i].get_fml());
|
||||
|
||||
TRACE("quasi_macros", tout << "Occurrences: " << std::endl;
|
||||
for (occurrences_map::iterator it = m_occurrences.begin();
|
||||
|
@ -277,10 +315,10 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
|||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
app_ref a(m_manager);
|
||||
expr_ref t(m_manager);
|
||||
if (is_quasi_macro(exprs[i], a, t)) {
|
||||
if (is_quasi_macro(exprs[i].get_fml(), a, t)) {
|
||||
quantifier_ref macro(m_manager);
|
||||
quasi_macro_to_macro(to_quantifier(exprs[i]), a, t, macro);
|
||||
TRACE("quasi_macros", tout << "Found quasi macro: " << mk_pp(exprs[i], m_manager) << std::endl;
|
||||
quasi_macro_to_macro(to_quantifier(exprs[i].get_fml()), a, t, macro);
|
||||
TRACE("quasi_macros", tout << "Found quasi macro: " << mk_pp(exprs[i].get_fml(), m_manager) << std::endl;
|
||||
tout << "Macro: " << mk_pp(macro, m_manager) << std::endl; );
|
||||
proof * pr = 0;
|
||||
if (m_manager.proofs_enabled())
|
||||
|
@ -293,28 +331,57 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
|||
return res;
|
||||
}
|
||||
|
||||
void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const* deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector& new_deps) {
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
expr_ref r(m_manager), rs(m_manager);
|
||||
proof_ref pr(m_manager), ps(m_manager);
|
||||
expr_dependency_ref dep(m_manager);
|
||||
proof * p = m_manager.proofs_enabled() ? prs[i] : 0;
|
||||
m_macro_manager.expand_macros(exprs[i], p, r, pr);
|
||||
m_simplifier(r, rs, ps);
|
||||
new_exprs.push_back(rs);
|
||||
|
||||
m_macro_manager.expand_macros(exprs[i], p, deps[i], r, pr, dep);
|
||||
m_rewriter(r);
|
||||
new_exprs.push_back(r);
|
||||
new_prs.push_back(ps);
|
||||
new_deps.push_back(dep);
|
||||
}
|
||||
}
|
||||
|
||||
bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
|
||||
if (find_macros(n, exprs)) {
|
||||
apply_macros(n, exprs, prs, new_exprs, new_prs);
|
||||
apply_macros(n, exprs, prs, deps, new_exprs, new_prs, new_deps);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// just copy them over
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
new_exprs.push_back(exprs[i]);
|
||||
if (m_manager.proofs_enabled())
|
||||
new_prs.push_back(prs[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void quasi_macros::apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
expr_ref r(m_manager), rs(m_manager);
|
||||
proof_ref pr(m_manager), ps(m_manager);
|
||||
proof * p = m_manager.proofs_enabled() ? fmls[i].get_proof() : 0;
|
||||
expr_dependency_ref dep(m_manager);
|
||||
m_macro_manager.expand_macros(fmls[i].get_fml(), p, 0, r, pr, dep);
|
||||
m_rewriter(r);
|
||||
new_fmls.push_back(justified_expr(m_manager, r, pr));
|
||||
}
|
||||
}
|
||||
|
||||
bool quasi_macros::operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
if (find_macros(n, fmls)) {
|
||||
apply_macros(n, fmls, new_fmls);
|
||||
return true;
|
||||
} else {
|
||||
// just copy them over
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
new_exprs.push_back(exprs[i]);
|
||||
if (m_manager.proofs_enabled())
|
||||
new_prs.push_back(prs[i]);
|
||||
new_fmls.push_back(fmls[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ Revision History:
|
|||
#define QUASI_MACROS_H_
|
||||
|
||||
#include<sstream>
|
||||
#include"macro_manager.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"simplifier.h"
|
||||
#include "ast/justified_expr.h"
|
||||
#include "ast/macros/macro_manager.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
|
||||
/**
|
||||
\brief Finds quasi macros and applies them.
|
||||
|
@ -32,38 +32,44 @@ class quasi_macros {
|
|||
|
||||
ast_manager & m_manager;
|
||||
macro_manager & m_macro_manager;
|
||||
simplifier & m_simplifier;
|
||||
th_rewriter m_rewriter;
|
||||
occurrences_map m_occurrences;
|
||||
ptr_vector<expr> m_todo;
|
||||
ptr_vector<expr> m_todo;
|
||||
|
||||
vector<symbol> m_new_var_names;
|
||||
expr_ref_vector m_new_vars;
|
||||
expr_ref_vector m_new_eqs;
|
||||
sort_ref_vector m_new_qsorts;
|
||||
std::stringstream m_new_name;
|
||||
std::stringstream m_new_name;
|
||||
expr_mark m_visited_once;
|
||||
expr_mark m_visited_more;
|
||||
|
||||
|
||||
bool is_unique(func_decl * f) const;
|
||||
bool is_non_ground_uninterp(expr const * e) const;
|
||||
bool fully_depends_on(app * a, quantifier * q) const;
|
||||
bool fully_depends_on(app * a, quantifier * q) const;
|
||||
bool depends_on(expr * e, func_decl * f) const;
|
||||
|
||||
bool is_quasi_macro(expr * e, app_ref & a, expr_ref &v) const;
|
||||
bool is_quasi_macro(expr * e, app_ref & a, expr_ref &v) const;
|
||||
void quasi_macro_to_macro(quantifier * q, app * a, expr * t, quantifier_ref & macro);
|
||||
|
||||
void find_occurrences(expr * e);
|
||||
bool find_macros(unsigned n, expr * const * exprs);
|
||||
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
bool find_macros(unsigned n, justified_expr const* expr);
|
||||
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const* deps,
|
||||
expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector& new_deps);
|
||||
void apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
|
||||
|
||||
public:
|
||||
quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
|
||||
quasi_macros(ast_manager & m, macro_manager & mm);
|
||||
~quasi_macros();
|
||||
|
||||
|
||||
/**
|
||||
\brief Find pure function macros and apply them.
|
||||
*/
|
||||
bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
// bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
bool operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
|
||||
bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,12 +16,12 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"defined_names.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"used_vars.h"
|
||||
#include"var_subst.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
||||
struct defined_names::impl {
|
||||
typedef obj_map<expr, app *> expr2name;
|
||||
|
|
|
@ -20,7 +20,7 @@ Revision History:
|
|||
#ifndef DEFINED_NAMES_H_
|
||||
#define DEFINED_NAMES_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
/**
|
||||
\brief Mapping from expressions to skolem functions that are used to name them.
|
||||
|
|
|
@ -16,9 +16,9 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"name_exprs.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/normal_forms/name_exprs.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
class name_exprs_core : public name_exprs {
|
||||
struct cfg : public default_rewriter_cfg {
|
||||
|
|
|
@ -19,8 +19,8 @@ Notes:
|
|||
#ifndef NAME_EXPRS_H_
|
||||
#define NAME_EXPRS_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"defined_names.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
|
||||
class expr_predicate {
|
||||
public:
|
||||
|
|
|
@ -17,18 +17,18 @@ Notes:
|
|||
Major revision on 2011-10-06
|
||||
|
||||
--*/
|
||||
#include"nnf.h"
|
||||
#include"nnf_params.hpp"
|
||||
#include"warning.h"
|
||||
#include"used_vars.h"
|
||||
#include"well_sorted.h"
|
||||
#include"var_subst.h"
|
||||
#include "ast/normal_forms/nnf.h"
|
||||
#include "ast/normal_forms/nnf_params.hpp"
|
||||
#include "util/warning.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
#include"name_exprs.h"
|
||||
#include"act_cache.h"
|
||||
#include"cooperate.h"
|
||||
#include "ast/normal_forms/name_exprs.h"
|
||||
#include "ast/act_cache.h"
|
||||
#include "util/cooperate.h"
|
||||
|
||||
#include"ast_smt2_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
/**
|
||||
\brief NNF translation mode. The cheapest mode is NNF_SKOLEM, and
|
||||
|
|
|
@ -20,9 +20,9 @@ Notes:
|
|||
#ifndef NNF_H_
|
||||
#define NNF_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"params.h"
|
||||
#include"defined_names.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/params.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
|
||||
class nnf {
|
||||
struct imp;
|
||||
|
|
|
@ -16,10 +16,10 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include"pull_quant.h"
|
||||
#include"var_subst.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"ast_pp.h"
|
||||
#include "ast/normal_forms/pull_quant.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
||||
struct pull_quant::imp {
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ Notes:
|
|||
#ifndef PULL_QUANT_H_
|
||||
#define PULL_QUANT_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
/**
|
||||
\brief Pull nested quantifiers in a formula.
|
||||
|
|
|
@ -17,7 +17,7 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include"num_occurs.h"
|
||||
#include "ast/num_occurs.h"
|
||||
|
||||
void num_occurs::process(expr * t, expr_fast_mark1 & visited) {
|
||||
ptr_buffer<expr, 128> stack;
|
||||
|
|
|
@ -19,8 +19,8 @@ Revision History:
|
|||
#ifndef NUM_OCCURS_H_
|
||||
#define NUM_OCCURS_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
|
||||
/**
|
||||
\brief Functor for computing the number of occurrences of each sub-expression in a expression F.
|
||||
|
|
|
@ -16,9 +16,9 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"occurs.h"
|
||||
#include "ast/occurs.h"
|
||||
|
||||
#include"for_each_expr.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
|
|
@ -29,7 +29,7 @@ z3_add_component(pattern
|
|||
${CMAKE_CURRENT_BINARY_DIR}/database.h
|
||||
COMPONENT_DEPENDENCIES
|
||||
normal_forms
|
||||
simplifier
|
||||
rewriter
|
||||
smt2parser
|
||||
PYG_FILES
|
||||
pattern_inference_params_helper.pyg
|
||||
|
|
|
@ -29,13 +29,13 @@ Notes:
|
|||
|
||||
--*/
|
||||
|
||||
#include"ast.h"
|
||||
#include"expr_pattern_match.h"
|
||||
#include"for_each_ast.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include"cmd_context.h"
|
||||
#include"smt2parser.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/pattern/expr_pattern_match.h"
|
||||
#include "ast/for_each_ast.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "cmd_context/cmd_context.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
|
||||
expr_pattern_match::expr_pattern_match(ast_manager & manager):
|
||||
m_manager(manager), m_precompiled(manager) {
|
||||
|
|
|
@ -20,8 +20,8 @@ Notes:
|
|||
#ifndef EXPR_PATTERN_MATCH_H_
|
||||
#define EXPR_PATTERN_MATCH_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"map.h"
|
||||
#include "ast/ast.h"
|
||||
#include "util/map.h"
|
||||
|
||||
class expr_pattern_match {
|
||||
|
||||
|
|
|
@ -16,15 +16,17 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"pattern_inference.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_util.h"
|
||||
#include"warning.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"pull_quant.h"
|
||||
#include"well_sorted.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
#include "util/warning.h"
|
||||
#include "ast/pattern/pattern_inference.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/normal_forms/pull_quant.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
|
||||
void smaller_pattern::save(expr * p1, expr * p2) {
|
||||
expr_pair e(p1, p2);
|
||||
|
@ -54,7 +56,7 @@ bool smaller_pattern::process(expr * p1, expr * p2) {
|
|||
unsigned num1 = app1->get_num_args();
|
||||
if (num1 != app2->get_num_args() || app1->get_decl() != app2->get_decl())
|
||||
return false;
|
||||
for (unsigned i = 0; i < num1; i++)
|
||||
for (unsigned i = 0; i < num1; i++)
|
||||
save(app1->get_arg(i), app2->get_arg(i));
|
||||
break;
|
||||
}
|
||||
|
@ -67,7 +69,7 @@ bool smaller_pattern::process(expr * p1, expr * p2) {
|
|||
return false;
|
||||
}
|
||||
// it is a variable bound by an external quantifier
|
||||
else if (p1 != p2)
|
||||
else if (p1 != p2)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
@ -87,8 +89,20 @@ bool smaller_pattern::operator()(unsigned num_bindings, expr * p1, expr * p2) {
|
|||
return process(p1, p2);
|
||||
}
|
||||
|
||||
pattern_inference::pattern_inference(ast_manager & m, pattern_inference_params & params):
|
||||
simplifier(m),
|
||||
|
||||
#ifdef _TRACE
|
||||
static void dump_app_vector(std::ostream & out, ptr_vector<app> const & v, ast_manager & m) {
|
||||
for (app * e : v)
|
||||
out << mk_pp(e, m) << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include "ast/pattern/database.h"
|
||||
|
||||
|
||||
pattern_inference_cfg::pattern_inference_cfg(ast_manager & m, pattern_inference_params & params):
|
||||
m(m),
|
||||
m_params(params),
|
||||
m_bfid(m.get_basic_family_id()),
|
||||
m_afid(m.mk_family_id("arith")),
|
||||
|
@ -102,10 +116,9 @@ pattern_inference::pattern_inference(ast_manager & m, pattern_inference_params &
|
|||
m_database(m) {
|
||||
if (params.m_pi_arith == AP_NO)
|
||||
register_forbidden_family(m_afid);
|
||||
enable_ac_support(false);
|
||||
}
|
||||
|
||||
void pattern_inference::collect::operator()(expr * n, unsigned num_bindings) {
|
||||
void pattern_inference_cfg::collect::operator()(expr * n, unsigned num_bindings) {
|
||||
SASSERT(m_info.empty());
|
||||
SASSERT(m_todo.empty());
|
||||
SASSERT(m_cache.empty());
|
||||
|
@ -125,7 +138,7 @@ void pattern_inference::collect::operator()(expr * n, unsigned num_bindings) {
|
|||
reset();
|
||||
}
|
||||
|
||||
inline void pattern_inference::collect::visit(expr * n, unsigned delta, bool & visited) {
|
||||
inline void pattern_inference_cfg::collect::visit(expr * n, unsigned delta, bool & visited) {
|
||||
entry e(n, delta);
|
||||
if (!m_cache.contains(e)) {
|
||||
m_todo.push_back(e);
|
||||
|
@ -133,11 +146,11 @@ inline void pattern_inference::collect::visit(expr * n, unsigned delta, bool & v
|
|||
}
|
||||
}
|
||||
|
||||
bool pattern_inference::collect::visit_children(expr * n, unsigned delta) {
|
||||
bool pattern_inference_cfg::collect::visit_children(expr * n, unsigned delta) {
|
||||
bool visited = true;
|
||||
unsigned i;
|
||||
switch (n->get_kind()) {
|
||||
case AST_APP:
|
||||
case AST_APP:
|
||||
i = to_app(n)->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
|
@ -153,13 +166,13 @@ bool pattern_inference::collect::visit_children(expr * n, unsigned delta) {
|
|||
return visited;
|
||||
}
|
||||
|
||||
inline void pattern_inference::collect::save(expr * n, unsigned delta, info * i) {
|
||||
inline void pattern_inference_cfg::collect::save(expr * n, unsigned delta, info * i) {
|
||||
m_cache.insert(entry(n, delta), i);
|
||||
if (i != 0)
|
||||
m_info.push_back(i);
|
||||
}
|
||||
|
||||
void pattern_inference::collect::save_candidate(expr * n, unsigned delta) {
|
||||
void pattern_inference_cfg::collect::save_candidate(expr * n, unsigned delta) {
|
||||
switch (n->get_kind()) {
|
||||
case AST_VAR: {
|
||||
unsigned idx = to_var(n)->get_idx();
|
||||
|
@ -187,14 +200,14 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) {
|
|||
save(n, delta, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (c->get_num_args() == 0) {
|
||||
save(n, delta, alloc(info, m, n, uint_set(), 1));
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_buffer<expr> buffer;
|
||||
bool changed = false; // false if none of the children is mapped to a node different from itself.
|
||||
bool changed = false; // false if none of the children is mapped to a node different from itself.
|
||||
uint_set free_vars;
|
||||
unsigned size = 1;
|
||||
unsigned num = c->get_num_args();
|
||||
|
@ -216,7 +229,7 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) {
|
|||
if (child != child_info->m_node.get())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
app * new_node = 0;
|
||||
if (changed)
|
||||
new_node = m.mk_app(decl, buffer.size(), buffer.c_ptr());
|
||||
|
@ -229,11 +242,11 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) {
|
|||
//
|
||||
// Remark: The rule above has an exception. The operators (div, idiv, mod) are allowed to be
|
||||
// used as patterns even when they are not nested in other terms. The motivation is that
|
||||
// Z3 currently doesn't implement them (i.e., they are uninterpreted). So, some users add axioms
|
||||
// Z3 currently doesn't implement them (i.e., they are uninterpreted). So, some users add axioms
|
||||
// stating properties about these operators.
|
||||
family_id fid = c->get_family_id();
|
||||
decl_kind k = c->get_decl_kind();
|
||||
if (!free_vars.empty() &&
|
||||
if (!free_vars.empty() &&
|
||||
(fid != m_afid || (fid == m_afid && !m_owner.m_nested_arith_only && (k == OP_DIV || k == OP_IDIV || k == OP_MOD || k == OP_REM || k == OP_MUL)))) {
|
||||
TRACE("pattern_inference", tout << "potential candidate: \n" << mk_pp(new_node, m) << "\n";);
|
||||
m_owner.add_candidate(new_node, free_vars, size);
|
||||
|
@ -247,14 +260,14 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) {
|
|||
}
|
||||
|
||||
|
||||
void pattern_inference::collect::reset() {
|
||||
void pattern_inference_cfg::collect::reset() {
|
||||
m_cache.reset();
|
||||
std::for_each(m_info.begin(), m_info.end(), delete_proc<info>());
|
||||
m_info.reset();
|
||||
SASSERT(m_todo.empty());
|
||||
}
|
||||
|
||||
void pattern_inference::add_candidate(app * n, uint_set const & free_vars, unsigned size) {
|
||||
void pattern_inference_cfg::add_candidate(app * n, uint_set const & free_vars, unsigned size) {
|
||||
for (unsigned i = 0; i < m_num_no_patterns; i++) {
|
||||
if (n == m_no_patterns[i])
|
||||
return;
|
||||
|
@ -271,7 +284,7 @@ void pattern_inference::add_candidate(app * n, uint_set const & free_vars, unsig
|
|||
\brief Copy the non-looping patterns in m_candidates to result when m_params.m_pi_block_loop_patterns = true.
|
||||
Otherwise, copy m_candidates to result.
|
||||
*/
|
||||
void pattern_inference::filter_looping_patterns(ptr_vector<app> & result) {
|
||||
void pattern_inference_cfg::filter_looping_patterns(ptr_vector<app> & result) {
|
||||
unsigned num = m_candidates.size();
|
||||
for (unsigned i1 = 0; i1 < num; i1++) {
|
||||
app * n1 = m_candidates.get(i1);
|
||||
|
@ -288,7 +301,7 @@ void pattern_inference::filter_looping_patterns(ptr_vector<app> & result) {
|
|||
uint_set const & s2 = e2->get_data().m_value.m_free_vars;
|
||||
// Remark: the comparison operator only makes sense if both AST nodes
|
||||
// contain the same number of variables.
|
||||
// Example:
|
||||
// Example:
|
||||
// (f X Y) <: (f (g X Z W) Y)
|
||||
if (s1 == s2 && m_le(m_num_bindings, n1, n2) && !m_le(m_num_bindings, n2, n1)) {
|
||||
smaller = true;
|
||||
|
@ -310,7 +323,7 @@ void pattern_inference::filter_looping_patterns(ptr_vector<app> & result) {
|
|||
|
||||
|
||||
|
||||
inline void pattern_inference::contains_subpattern::save(expr * n) {
|
||||
inline void pattern_inference_cfg::contains_subpattern::save(expr * n) {
|
||||
unsigned id = n->get_id();
|
||||
m_already_processed.assure_domain(id);
|
||||
if (!m_already_processed.contains(id)) {
|
||||
|
@ -319,7 +332,7 @@ inline void pattern_inference::contains_subpattern::save(expr * n) {
|
|||
}
|
||||
}
|
||||
|
||||
bool pattern_inference::contains_subpattern::operator()(expr * n) {
|
||||
bool pattern_inference_cfg::contains_subpattern::operator()(expr * n) {
|
||||
m_already_processed.reset();
|
||||
m_todo.reset();
|
||||
expr2info::obj_map_entry * _e = m_owner.m_candidates_info.find_core(n);
|
||||
|
@ -360,7 +373,7 @@ bool pattern_inference::contains_subpattern::operator()(expr * n) {
|
|||
Return true if n contains a direct/indirect child that is also a
|
||||
pattern, and contains the same number of free variables.
|
||||
*/
|
||||
inline bool pattern_inference::contains_subpattern(expr * n) {
|
||||
inline bool pattern_inference_cfg::contains_subpattern(expr * n) {
|
||||
return m_contains_subpattern(n);
|
||||
}
|
||||
|
||||
|
@ -372,18 +385,15 @@ inline bool pattern_inference::contains_subpattern(expr * n) {
|
|||
Remark: Every pattern p in patterns is also a member of
|
||||
m_pattern_map.
|
||||
*/
|
||||
void pattern_inference::filter_bigger_patterns(ptr_vector<app> const & patterns, ptr_vector<app> & result) {
|
||||
ptr_vector<app>::const_iterator it = patterns.begin();
|
||||
ptr_vector<app>::const_iterator end = patterns.end();
|
||||
for (; it != end; ++it) {
|
||||
app * curr = *it;
|
||||
void pattern_inference_cfg::filter_bigger_patterns(ptr_vector<app> const & patterns, ptr_vector<app> & result) {
|
||||
for (app * curr : patterns) {
|
||||
if (!contains_subpattern(curr))
|
||||
result.push_back(curr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool pattern_inference::pattern_weight_lt::operator()(expr * n1, expr * n2) const {
|
||||
bool pattern_inference_cfg::pattern_weight_lt::operator()(expr * n1, expr * n2) const {
|
||||
expr2info::obj_map_entry * e1 = m_candidates_info.find_core(n1);
|
||||
expr2info::obj_map_entry * e2 = m_candidates_info.find_core(n2);
|
||||
SASSERT(e1 != 0);
|
||||
|
@ -401,13 +411,10 @@ bool pattern_inference::pattern_weight_lt::operator()(expr * n1, expr * n2) cons
|
|||
variables, then it is copied to remaining_candidate_patterns. The
|
||||
new patterns are stored in result.
|
||||
*/
|
||||
void pattern_inference::candidates2unary_patterns(ptr_vector<app> const & candidate_patterns,
|
||||
void pattern_inference_cfg::candidates2unary_patterns(ptr_vector<app> const & candidate_patterns,
|
||||
ptr_vector<app> & remaining_candidate_patterns,
|
||||
app_ref_buffer & result) {
|
||||
ptr_vector<app>::const_iterator it = candidate_patterns.begin();
|
||||
ptr_vector<app>::const_iterator end = candidate_patterns.end();
|
||||
for (; it != end; ++it) {
|
||||
app * candidate = *it;
|
||||
for (app * candidate : candidate_patterns) {
|
||||
expr2info::obj_map_entry * e = m_candidates_info.find_core(candidate);
|
||||
info const & i = e->get_data().m_value;
|
||||
if (i.m_free_vars.num_elems() == m_num_bindings) {
|
||||
|
@ -421,12 +428,12 @@ void pattern_inference::candidates2unary_patterns(ptr_vector<app> const & candid
|
|||
}
|
||||
|
||||
// TODO: this code is too inefficient when the number of candidate
|
||||
// patterns is too big.
|
||||
// patterns is too big.
|
||||
// HACK: limit the number of case-splits:
|
||||
#define MAX_SPLITS 32
|
||||
|
||||
void pattern_inference::candidates2multi_patterns(unsigned max_num_patterns,
|
||||
ptr_vector<app> const & candidate_patterns,
|
||||
void pattern_inference_cfg::candidates2multi_patterns(unsigned max_num_patterns,
|
||||
ptr_vector<app> const & candidate_patterns,
|
||||
app_ref_buffer & result) {
|
||||
SASSERT(!candidate_patterns.empty());
|
||||
m_pre_patterns.push_back(alloc(pre_pattern));
|
||||
|
@ -464,31 +471,23 @@ void pattern_inference::candidates2multi_patterns(unsigned max_num_patterns,
|
|||
m_pre_patterns.push_back(curr);
|
||||
}
|
||||
}
|
||||
TRACE("pattern_inference", tout << "m_pre_patterns.size(): " << m_pre_patterns.size() <<
|
||||
TRACE("pattern_inference", tout << "m_pre_patterns.size(): " << m_pre_patterns.size() <<
|
||||
"\nnum_splits: " << num_splits << "\n";);
|
||||
}
|
||||
}
|
||||
|
||||
void pattern_inference::reset_pre_patterns() {
|
||||
void pattern_inference_cfg::reset_pre_patterns() {
|
||||
std::for_each(m_pre_patterns.begin(), m_pre_patterns.end(), delete_proc<pre_pattern>());
|
||||
m_pre_patterns.reset();
|
||||
}
|
||||
|
||||
#ifdef _TRACE
|
||||
static void dump_app_vector(std::ostream & out, ptr_vector<app> const & v, ast_manager & m) {
|
||||
ptr_vector<app>::const_iterator it = v.begin();
|
||||
ptr_vector<app>::const_iterator end = v.end();
|
||||
for (; it != end; ++it)
|
||||
out << mk_pp(*it, m) << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
bool pattern_inference::is_forbidden(app * n) const {
|
||||
bool pattern_inference_cfg::is_forbidden(app * n) const {
|
||||
func_decl const * decl = n->get_decl();
|
||||
if (is_ground(n))
|
||||
return false;
|
||||
// Remark: skolem constants should not be used in patterns, since they do not
|
||||
// occur outside of the quantifier. That is, Z3 will never match this kind of
|
||||
// Remark: skolem constants should not be used in patterns, since they do not
|
||||
// occur outside of the quantifier. That is, Z3 will never match this kind of
|
||||
// pattern.
|
||||
if (m_params.m_pi_avoid_skolems && decl->is_skolem()) {
|
||||
CTRACE("pattern_inference_skolem", decl->is_skolem(), tout << "ignoring: " << mk_pp(n, m) << "\n";);
|
||||
|
@ -499,14 +498,11 @@ bool pattern_inference::is_forbidden(app * n) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool pattern_inference::has_preferred_patterns(ptr_vector<app> & candidate_patterns, app_ref_buffer & result) {
|
||||
bool pattern_inference_cfg::has_preferred_patterns(ptr_vector<app> & candidate_patterns, app_ref_buffer & result) {
|
||||
if (m_preferred.empty())
|
||||
return false;
|
||||
bool found = false;
|
||||
ptr_vector<app>::const_iterator it = candidate_patterns.begin();
|
||||
ptr_vector<app>::const_iterator end = candidate_patterns.end();
|
||||
for (; it != end; ++it) {
|
||||
app * candidate = *it;
|
||||
for (app * candidate : candidate_patterns) {
|
||||
if (m_preferred.contains(to_app(candidate)->get_decl())) {
|
||||
expr2info::obj_map_entry * e = m_candidates_info.find_core(candidate);
|
||||
info const & i = e->get_data().m_value;
|
||||
|
@ -521,9 +517,9 @@ bool pattern_inference::has_preferred_patterns(ptr_vector<app> & candidate_patte
|
|||
return found;
|
||||
}
|
||||
|
||||
void pattern_inference::mk_patterns(unsigned num_bindings,
|
||||
expr * n,
|
||||
unsigned num_no_patterns,
|
||||
void pattern_inference_cfg::mk_patterns(unsigned num_bindings,
|
||||
expr * n,
|
||||
unsigned num_no_patterns,
|
||||
expr * const * no_patterns,
|
||||
app_ref_buffer & result) {
|
||||
m_num_bindings = num_bindings;
|
||||
|
@ -532,7 +528,7 @@ void pattern_inference::mk_patterns(unsigned num_bindings,
|
|||
|
||||
m_collect(n, num_bindings);
|
||||
|
||||
TRACE("pattern_inference",
|
||||
TRACE("pattern_inference",
|
||||
tout << mk_pp(n, m);
|
||||
tout << "\ncandidates:\n";
|
||||
unsigned num = m_candidates.size();
|
||||
|
@ -558,7 +554,7 @@ void pattern_inference::mk_patterns(unsigned num_bindings,
|
|||
m_tmp1.reset();
|
||||
candidates2unary_patterns(m_tmp2, m_tmp1, result);
|
||||
unsigned num_extra_multi_patterns = m_params.m_pi_max_multi_patterns;
|
||||
if (result.empty())
|
||||
if (result.empty())
|
||||
num_extra_multi_patterns++;
|
||||
if (num_extra_multi_patterns > 0 && !m_tmp1.empty()) {
|
||||
// m_pattern_weight_lt is not a total order
|
||||
|
@ -576,75 +572,63 @@ void pattern_inference::mk_patterns(unsigned num_bindings,
|
|||
m_candidates.reset();
|
||||
}
|
||||
|
||||
#include"database.h" // defines g_pattern_database
|
||||
|
||||
void pattern_inference::reduce1_quantifier(quantifier * q) {
|
||||
bool pattern_inference_cfg::reduce_quantifier(
|
||||
quantifier * q,
|
||||
expr * new_body,
|
||||
expr * const *, // new_patterns
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
||||
TRACE("pattern_inference", tout << "processing:\n" << mk_pp(q, m) << "\n";);
|
||||
if (!q->is_forall()) {
|
||||
simplifier::reduce1_quantifier(q);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
int weight = q->get_weight();
|
||||
|
||||
if (m_params.m_pi_use_database) {
|
||||
m_database.initialize(g_pattern_database);
|
||||
app_ref_vector new_patterns(m);
|
||||
m_database.initialize(g_pattern_database);
|
||||
unsigned new_weight;
|
||||
if (m_database.match_quantifier(q, new_patterns, new_weight)) {
|
||||
#ifdef Z3DEBUG
|
||||
for (unsigned i = 0; i < new_patterns.size(); i++) { SASSERT(is_well_sorted(m, new_patterns.get(i))); }
|
||||
#endif
|
||||
DEBUG_CODE(for (unsigned i = 0; i < new_patterns.size(); i++) { SASSERT(is_well_sorted(m, new_patterns.get(i))); });
|
||||
quantifier_ref new_q(m);
|
||||
if (q->get_num_patterns() > 0) {
|
||||
// just update the weight...
|
||||
TRACE("pattern_inference", tout << "updating weight to: " << new_weight << "\n" << mk_pp(q, m) << "\n";);
|
||||
new_q = m.update_quantifier_weight(q, new_weight);
|
||||
result = m.update_quantifier_weight(q, new_weight);
|
||||
}
|
||||
else {
|
||||
quantifier_ref tmp(m);
|
||||
tmp = m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), q->get_expr());
|
||||
new_q = m.update_quantifier_weight(tmp, new_weight);
|
||||
tmp = m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), q->get_expr());
|
||||
result = m.update_quantifier_weight(tmp, new_weight);
|
||||
TRACE("pattern_inference", tout << "found patterns in database, weight: " << new_weight << "\n" << mk_pp(new_q, m) << "\n";);
|
||||
}
|
||||
proof * pr = 0;
|
||||
if (m.fine_grain_proofs())
|
||||
pr = m.mk_rewrite(q, new_q);
|
||||
cache_result(q, new_q, pr);
|
||||
return;
|
||||
result_pr = m.mk_rewrite(q, new_q);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (q->get_num_patterns() > 0) {
|
||||
simplifier::reduce1_quantifier(q);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_params.m_pi_nopat_weight >= 0)
|
||||
weight = m_params.m_pi_nopat_weight;
|
||||
|
||||
SASSERT(q->get_num_patterns() == 0);
|
||||
expr * new_body;
|
||||
proof * new_body_pr;
|
||||
get_cached(q->get_expr(), new_body, new_body_pr);
|
||||
|
||||
ptr_buffer<expr> new_no_patterns;
|
||||
unsigned num_no_patterns = q->get_num_no_patterns();
|
||||
for (unsigned i = 0; i < num_no_patterns; i++) {
|
||||
expr * new_pattern;
|
||||
proof * new_pattern_pr;
|
||||
get_cached(q->get_no_pattern(i), new_pattern, new_pattern_pr);
|
||||
new_no_patterns.push_back(new_pattern);
|
||||
}
|
||||
|
||||
app_ref_buffer new_patterns(m);
|
||||
|
||||
if (m_params.m_pi_arith == AP_CONSERVATIVE)
|
||||
m_forbidden.push_back(m_afid);
|
||||
|
||||
mk_patterns(q->get_num_decls(), new_body, new_no_patterns.size(), new_no_patterns.c_ptr(), new_patterns);
|
||||
|
||||
if (new_patterns.empty() && !new_no_patterns.empty()) {
|
||||
app_ref_buffer new_patterns(m);
|
||||
unsigned num_no_patterns = q->get_num_no_patterns();
|
||||
mk_patterns(q->get_num_decls(), new_body, num_no_patterns, new_no_patterns, new_patterns);
|
||||
|
||||
if (new_patterns.empty() && num_no_patterns > 0) {
|
||||
if (new_patterns.empty()) {
|
||||
mk_patterns(q->get_num_decls(), new_body, 0, 0, new_patterns);
|
||||
if (m_params.m_pi_warnings && !new_patterns.empty()) {
|
||||
|
@ -652,65 +636,61 @@ void pattern_inference::reduce1_quantifier(quantifier * q) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_params.m_pi_arith == AP_CONSERVATIVE) {
|
||||
m_forbidden.pop_back();
|
||||
if (new_patterns.empty()) {
|
||||
flet<bool> l1(m_block_loop_patterns, false); // allow looping patterns
|
||||
mk_patterns(q->get_num_decls(), new_body, new_no_patterns.size(), new_no_patterns.c_ptr(), new_patterns);
|
||||
mk_patterns(q->get_num_decls(), new_body, num_no_patterns, new_no_patterns, new_patterns);
|
||||
if (!new_patterns.empty()) {
|
||||
weight = std::max(weight, static_cast<int>(m_params.m_pi_arith_weight));
|
||||
if (m_params.m_pi_warnings) {
|
||||
warning_msg("using arith. in pattern (quantifier id: %s), the weight was increased to %d (this value can be modified using PI_ARITH_WEIGHT=<val>).",
|
||||
warning_msg("using arith. in pattern (quantifier id: %s), the weight was increased to %d (this value can be modified using PI_ARITH_WEIGHT=<val>).",
|
||||
q->get_qid().str().c_str(), weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_params.m_pi_arith != AP_NO && new_patterns.empty()) {
|
||||
if (new_patterns.empty()) {
|
||||
flet<bool> l1(m_nested_arith_only, false); // try to find a non-nested arith pattern
|
||||
flet<bool> l2(m_block_loop_patterns, false); // allow looping patterns
|
||||
mk_patterns(q->get_num_decls(), new_body, new_no_patterns.size(), new_no_patterns.c_ptr(), new_patterns);
|
||||
mk_patterns(q->get_num_decls(), new_body, num_no_patterns, new_no_patterns, new_patterns);
|
||||
if (!new_patterns.empty()) {
|
||||
weight = std::max(weight, static_cast<int>(m_params.m_pi_non_nested_arith_weight));
|
||||
if (m_params.m_pi_warnings) {
|
||||
warning_msg("using non nested arith. pattern (quantifier id: %s), the weight was increased to %d (this value can be modified using PI_NON_NESTED_ARITH_WEIGHT=<val>).",
|
||||
q->get_qid().str().c_str(), weight);
|
||||
warning_msg("using non nested arith. pattern (quantifier id: %s), the weight was increased to %d (this value can be modified using PI_NON_NESTED_ARITH_WEIGHT=<val>).",
|
||||
q->get_qid().str().c_str(), weight);
|
||||
}
|
||||
// verbose_stream() << mk_pp(q, m) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_body);
|
||||
quantifier_ref new_q(m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_body), m);
|
||||
if (weight != q->get_weight())
|
||||
new_q = m.update_quantifier_weight(new_q, weight);
|
||||
proof_ref pr(m);
|
||||
if (m.fine_grain_proofs()) {
|
||||
if (new_body_pr == 0)
|
||||
new_body_pr = m.mk_reflexivity(new_body);
|
||||
pr = m.mk_quant_intro(q, new_q, new_body_pr);
|
||||
if (m.fine_grain_proofs()) {
|
||||
proof* new_body_pr = m.mk_reflexivity(new_body);
|
||||
result_pr = m.mk_quant_intro(q, new_q, new_body_pr);
|
||||
}
|
||||
|
||||
|
||||
if (new_patterns.empty() && m_params.m_pi_pull_quantifiers) {
|
||||
pull_quant pull(m);
|
||||
expr_ref new_expr(m);
|
||||
proof_ref new_pr(m);
|
||||
pull(new_q, new_expr, new_pr);
|
||||
quantifier * new_new_q = to_quantifier(new_expr);
|
||||
if (new_new_q != new_q) {
|
||||
mk_patterns(new_new_q->get_num_decls(), new_new_q->get_expr(), 0, 0, new_patterns);
|
||||
quantifier * result2 = to_quantifier(new_expr);
|
||||
if (result2 != new_q) {
|
||||
mk_patterns(result2->get_num_decls(), result2->get_expr(), 0, 0, new_patterns);
|
||||
if (!new_patterns.empty()) {
|
||||
if (m_params.m_pi_warnings) {
|
||||
warning_msg("pulled nested quantifier to be able to find an useable pattern (quantifier id: %s)", q->get_qid().str().c_str());
|
||||
}
|
||||
new_q = m.update_quantifier(new_new_q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_new_q->get_expr());
|
||||
new_q = m.update_quantifier(result2, new_patterns.size(), (expr**) new_patterns.c_ptr(), result2->get_expr());
|
||||
if (m.fine_grain_proofs()) {
|
||||
pr = m.mk_transitivity(pr, new_pr);
|
||||
pr = m.mk_transitivity(pr, m.mk_quant_intro(new_new_q, new_q, m.mk_reflexivity(new_q->get_expr())));
|
||||
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_reflexivity(new_q->get_expr())));
|
||||
}
|
||||
TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m) << "\n";);
|
||||
}
|
||||
|
@ -725,22 +705,21 @@ void pattern_inference::reduce1_quantifier(quantifier * q) {
|
|||
}
|
||||
|
||||
if (new_patterns.empty() && new_body == q->get_expr()) {
|
||||
cache_result(q, q, 0);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
cache_result(q, new_q, pr);
|
||||
|
||||
result = new_q;
|
||||
|
||||
IF_VERBOSE(10,
|
||||
verbose_stream() << "(smt.inferred-patterns :qid " << q->get_qid() << "\n";
|
||||
for (unsigned i = 0; i < new_patterns.size(); i++)
|
||||
verbose_stream() << " " << mk_ismt2_pp(new_patterns[i], m, 2) << "\n";
|
||||
verbose_stream() << ")\n"; );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// unused
|
||||
static void dump_expr_vector(std::ostream & out, ptr_vector<expr> const & v, ast_manager & m) {
|
||||
ptr_vector<expr>::const_iterator it = v.begin();
|
||||
ptr_vector<expr>::const_iterator end = v.end();
|
||||
for (; it != end; ++it)
|
||||
out << mk_pp(*it, m) << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
pattern_inference_rw::pattern_inference_rw(ast_manager& m, pattern_inference_params & params):
|
||||
rewriter_tpl<pattern_inference_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||
m_cfg(m, params)
|
||||
{}
|
||||
|
|
|
@ -19,16 +19,16 @@ Revision History:
|
|||
#ifndef PATTERN_INFERENCE_H_
|
||||
#define PATTERN_INFERENCE_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"simplifier.h"
|
||||
#include"pattern_inference_params.h"
|
||||
#include"vector.h"
|
||||
#include"uint_set.h"
|
||||
#include"nat_set.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"obj_pair_hashtable.h"
|
||||
#include"map.h"
|
||||
#include"expr_pattern_match.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/pattern/pattern_inference_params.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/uint_set.h"
|
||||
#include "util/nat_set.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "util/obj_pair_hashtable.h"
|
||||
#include "util/map.h"
|
||||
#include "ast/pattern/expr_pattern_match.h"
|
||||
|
||||
/**
|
||||
\brief A pattern p_1 is smaller than a pattern p_2 iff
|
||||
|
@ -60,7 +60,8 @@ public:
|
|||
bool operator()(unsigned num_bindings, expr * p1, expr * p2);
|
||||
};
|
||||
|
||||
class pattern_inference : public simplifier {
|
||||
class pattern_inference_cfg : public default_rewriter_cfg {
|
||||
ast_manager& m;
|
||||
pattern_inference_params & m_params;
|
||||
family_id m_bfid;
|
||||
family_id m_afid;
|
||||
|
@ -88,7 +89,7 @@ class pattern_inference : public simplifier {
|
|||
|
||||
typedef obj_map<expr, info> expr2info;
|
||||
|
||||
expr2info m_candidates_info; // candidate -> set of free vars + size
|
||||
expr2info m_candidates_info; // candidate -> set of free vars + size
|
||||
app_ref_vector m_candidates;
|
||||
|
||||
ptr_vector<app> m_tmp1;
|
||||
|
@ -136,7 +137,7 @@ class pattern_inference : public simplifier {
|
|||
};
|
||||
|
||||
ast_manager & m;
|
||||
pattern_inference & m_owner;
|
||||
pattern_inference_cfg & m_owner;
|
||||
family_id m_afid;
|
||||
unsigned m_num_bindings;
|
||||
typedef map<entry, info *, obj_hash<entry>, default_eq<entry> > cache;
|
||||
|
@ -150,7 +151,7 @@ class pattern_inference : public simplifier {
|
|||
void save_candidate(expr * n, unsigned delta);
|
||||
void reset();
|
||||
public:
|
||||
collect(ast_manager & m, pattern_inference & o):m(m), m_owner(o), m_afid(m.mk_family_id("arith")) {}
|
||||
collect(ast_manager & m, pattern_inference_cfg & o):m(m), m_owner(o), m_afid(m.mk_family_id("arith")) {}
|
||||
void operator()(expr * n, unsigned num_bindings);
|
||||
};
|
||||
|
||||
|
@ -165,12 +166,12 @@ class pattern_inference : public simplifier {
|
|||
void filter_bigger_patterns(ptr_vector<app> const & patterns, ptr_vector<app> & result);
|
||||
|
||||
class contains_subpattern {
|
||||
pattern_inference & m_owner;
|
||||
pattern_inference_cfg & m_owner;
|
||||
nat_set m_already_processed;
|
||||
ptr_vector<expr> m_todo;
|
||||
void save(expr * n);
|
||||
public:
|
||||
contains_subpattern(pattern_inference & owner):
|
||||
contains_subpattern(pattern_inference_cfg & owner):
|
||||
m_owner(owner) {}
|
||||
bool operator()(expr * n);
|
||||
};
|
||||
|
@ -214,10 +215,8 @@ class pattern_inference : public simplifier {
|
|||
expr * const * no_patterns, // IN patterns that should not be used.
|
||||
app_ref_buffer & result); // OUT result
|
||||
|
||||
virtual void reduce1_quantifier(quantifier * q);
|
||||
|
||||
public:
|
||||
pattern_inference(ast_manager & m, pattern_inference_params & params);
|
||||
pattern_inference_cfg(ast_manager & m, pattern_inference_params & params);
|
||||
|
||||
void register_forbidden_family(family_id fid) {
|
||||
SASSERT(fid != m_bfid);
|
||||
|
@ -232,6 +231,13 @@ public:
|
|||
m_preferred.insert(f);
|
||||
}
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr);
|
||||
|
||||
void register_preferred(unsigned num, func_decl * const * fs) { for (unsigned i = 0; i < num; i++) register_preferred(fs[i]); }
|
||||
|
||||
bool is_forbidden(func_decl const * decl) const {
|
||||
|
@ -244,5 +250,11 @@ public:
|
|||
bool is_forbidden(app * n) const;
|
||||
};
|
||||
|
||||
class pattern_inference_rw : public rewriter_tpl<pattern_inference_cfg> {
|
||||
pattern_inference_cfg m_cfg;
|
||||
public:
|
||||
pattern_inference_rw(ast_manager& m, pattern_inference_params & params);
|
||||
};
|
||||
|
||||
#endif /* PATTERN_INFERENCE_H_ */
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"pattern_inference_params.h"
|
||||
#include"pattern_inference_params_helper.hpp"
|
||||
#include "ast/pattern/pattern_inference_params.h"
|
||||
#include "ast/pattern/pattern_inference_params_helper.hpp"
|
||||
|
||||
void pattern_inference_params::updt_params(params_ref const & _p) {
|
||||
pattern_inference_params_helper p(_p);
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#ifndef PATTERN_INFERENCE_PARAMS_H_
|
||||
#define PATTERN_INFERENCE_PARAMS_H_
|
||||
|
||||
#include"params.h"
|
||||
#include "util/params.h"
|
||||
|
||||
enum arith_pattern_inference_kind {
|
||||
AP_NO, // do not infer patterns with arithmetic terms
|
||||
|
|
|
@ -17,8 +17,8 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include "pb_decl_plugin.h"
|
||||
#include "ast_util.h"
|
||||
#include "ast/pb_decl_plugin.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
pb_decl_plugin::pb_decl_plugin():
|
||||
m_at_most_sym("at-most"),
|
||||
|
|
|
@ -27,7 +27,7 @@ hence:
|
|||
#ifndef PB_DECL_PLUGIN_H_
|
||||
#define PB_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include "ast/ast.h"
|
||||
|
||||
enum pb_op_kind {
|
||||
OP_AT_MOST_K, // at most K Booleans are true.
|
||||
|
|
|
@ -16,8 +16,8 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"pp.h"
|
||||
#include"pp_params.hpp"
|
||||
#include "ast/pp.h"
|
||||
#include "ast/pp_params.hpp"
|
||||
using namespace format_ns;
|
||||
|
||||
static std::pair<unsigned, bool> space_upto_line_break(ast_manager & m, format * f) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue