feat(library/blast/blast): add support in blast for controlling whether macros are unfolded or not at whnf/normalize
This commit is contained in:
parent
24e4dbe353
commit
562d7b3e4a
2 changed files with 42 additions and 18 deletions
|
@ -37,6 +37,7 @@ static name * g_tmp_prefix = nullptr;
|
||||||
|
|
||||||
class blastenv {
|
class blastenv {
|
||||||
friend class scope_assignment;
|
friend class scope_assignment;
|
||||||
|
friend class scope_unfold_macro_pred;
|
||||||
typedef std::vector<tmp_type_context *> tmp_type_context_pool;
|
typedef std::vector<tmp_type_context *> tmp_type_context_pool;
|
||||||
typedef std::unique_ptr<tmp_type_context> tmp_type_context_ptr;
|
typedef std::unique_ptr<tmp_type_context> tmp_type_context_ptr;
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ class blastenv {
|
||||||
relation_info_getter m_rel_getter;
|
relation_info_getter m_rel_getter;
|
||||||
refl_info_getter m_refl_getter;
|
refl_info_getter m_refl_getter;
|
||||||
symm_info_getter m_symm_getter;
|
symm_info_getter m_symm_getter;
|
||||||
|
unfold_macro_pred m_unfold_macro_pred;
|
||||||
|
|
||||||
class tctx : public type_context {
|
class tctx : public type_context {
|
||||||
blastenv & m_benv;
|
blastenv & m_benv;
|
||||||
|
@ -73,38 +75,42 @@ class blastenv {
|
||||||
type_context(benv.m_env, benv.m_ios, benv.m_tmp_local_generator),
|
type_context(benv.m_env, benv.m_ios, benv.m_tmp_local_generator),
|
||||||
m_benv(benv) {}
|
m_benv(benv) {}
|
||||||
|
|
||||||
virtual bool is_extra_opaque(name const & n) const {
|
virtual bool is_extra_opaque(name const & n) const override {
|
||||||
// TODO(Leo): class and instances
|
// TODO(Leo): class and instances
|
||||||
return m_benv.m_not_reducible_pred(n) || m_benv.m_projection_info.contains(n);
|
return m_benv.m_not_reducible_pred(n) || m_benv.m_projection_info.contains(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool is_uvar(level const & l) const {
|
virtual bool should_unfold_macro(expr const & e) const override {
|
||||||
|
return m_benv.m_unfold_macro_pred(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool is_uvar(level const & l) const override {
|
||||||
return blast::is_uref(l);
|
return blast::is_uref(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool is_mvar(expr const & e) const {
|
virtual bool is_mvar(expr const & e) const override {
|
||||||
return blast::is_mref(e);
|
return blast::is_mref(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual optional<level> get_assignment(level const & u) const {
|
virtual optional<level> get_assignment(level const & u) const override {
|
||||||
if (auto v = m_benv.m_curr_state.get_uref_assignment(u))
|
if (auto v = m_benv.m_curr_state.get_uref_assignment(u))
|
||||||
return some_level(*v);
|
return some_level(*v);
|
||||||
else
|
else
|
||||||
return none_level();
|
return none_level();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual optional<expr> get_assignment(expr const & m) const {
|
virtual optional<expr> get_assignment(expr const & m) const override {
|
||||||
if (auto v = m_benv.m_curr_state.get_mref_assignment(m))
|
if (auto v = m_benv.m_curr_state.get_mref_assignment(m))
|
||||||
return some_expr(*v);
|
return some_expr(*v);
|
||||||
else
|
else
|
||||||
return none_expr();
|
return none_expr();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void update_assignment(level const & u, level const & v) {
|
virtual void update_assignment(level const & u, level const & v) override {
|
||||||
m_benv.m_curr_state.assign_uref(u, v);
|
m_benv.m_curr_state.assign_uref(u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void update_assignment(expr const & m, expr const & v) {
|
virtual void update_assignment(expr const & m, expr const & v) override {
|
||||||
m_benv.m_curr_state.assign_mref(m, v);
|
m_benv.m_curr_state.assign_mref(m, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +137,7 @@ class blastenv {
|
||||||
return check_href_core(d, h, visited);
|
return check_href_core(d, h, visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool validate_assignment(expr const & m, buffer<expr> const & locals, expr const & v) {
|
virtual bool validate_assignment(expr const & m, buffer<expr> const & locals, expr const & v) override {
|
||||||
// We must check
|
// We must check
|
||||||
// 1. All href in new_v are in the context of m.
|
// 1. All href in new_v are in the context of m.
|
||||||
// 2. The context of any (unassigned) mref in new_v must be a subset of the context of m.
|
// 2. The context of any (unassigned) mref in new_v must be a subset of the context of m.
|
||||||
|
@ -172,7 +178,7 @@ class blastenv {
|
||||||
/** \brief Return the type of a local constant (local or not).
|
/** \brief Return the type of a local constant (local or not).
|
||||||
\remark This method allows the customer to store the type of local constants
|
\remark This method allows the customer to store the type of local constants
|
||||||
in a different place. */
|
in a different place. */
|
||||||
virtual expr infer_local(expr const & e) const {
|
virtual expr infer_local(expr const & e) const override {
|
||||||
if (is_href(e)) {
|
if (is_href(e)) {
|
||||||
state const & s = m_benv.m_curr_state;
|
state const & s = m_benv.m_curr_state;
|
||||||
hypothesis const & h = s.get_hypothesis_decl(e);
|
hypothesis const & h = s.get_hypothesis_decl(e);
|
||||||
|
@ -182,7 +188,7 @@ class blastenv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual expr infer_metavar(expr const & m) const {
|
virtual expr infer_metavar(expr const & m) const override {
|
||||||
// Remark: we do not tolerate external meta-variables here.
|
// Remark: we do not tolerate external meta-variables here.
|
||||||
lean_assert(is_mref(m));
|
lean_assert(is_mref(m));
|
||||||
state const & s = m_benv.m_curr_state;
|
state const & s = m_benv.m_curr_state;
|
||||||
|
@ -191,24 +197,24 @@ class blastenv {
|
||||||
return d->get_type();
|
return d->get_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual level mk_uvar() {
|
virtual level mk_uvar() override {
|
||||||
return mk_fresh_uref();
|
return mk_fresh_uref();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual expr mk_mvar(expr const & type) {
|
virtual expr mk_mvar(expr const & type) override {
|
||||||
return m_benv.m_curr_state.mk_metavar(type);
|
return m_benv.m_curr_state.mk_metavar(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void push() {
|
virtual void push() override {
|
||||||
m_stack.push_back(m_benv.m_curr_state.save_assignment());
|
m_stack.push_back(m_benv.m_curr_state.save_assignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pop() {
|
virtual void pop() override {
|
||||||
m_benv.m_curr_state.restore_assignment(m_stack.back());
|
m_benv.m_curr_state.restore_assignment(m_stack.back());
|
||||||
m_stack.pop_back();
|
m_stack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void commit() {
|
virtual void commit() override {
|
||||||
m_stack.pop_back();
|
m_stack.pop_back();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -439,6 +445,7 @@ public:
|
||||||
m_rel_getter(mk_relation_info_getter(env)),
|
m_rel_getter(mk_relation_info_getter(env)),
|
||||||
m_refl_getter(mk_refl_info_getter(env)),
|
m_refl_getter(mk_refl_info_getter(env)),
|
||||||
m_symm_getter(mk_symm_info_getter(env)),
|
m_symm_getter(mk_symm_info_getter(env)),
|
||||||
|
m_unfold_macro_pred([](expr const &) { return true; }),
|
||||||
m_tctx(*this),
|
m_tctx(*this),
|
||||||
m_normalizer(m_tctx) {
|
m_normalizer(m_tctx) {
|
||||||
init_uref_mref_href_idxs();
|
init_uref_mref_href_idxs();
|
||||||
|
@ -782,6 +789,15 @@ void scope_assignment::commit() {
|
||||||
m_keep = true;
|
m_keep = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope_unfold_macro_pred::scope_unfold_macro_pred(unfold_macro_pred const & pred):
|
||||||
|
m_old_pred(g_blastenv->m_unfold_macro_pred) {
|
||||||
|
g_blastenv->m_unfold_macro_pred = pred;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_unfold_macro_pred::~scope_unfold_macro_pred() {
|
||||||
|
g_blastenv->m_unfold_macro_pred = m_old_pred;
|
||||||
|
}
|
||||||
|
|
||||||
struct scope_debug::imp {
|
struct scope_debug::imp {
|
||||||
scoped_expr_caching m_scope1;
|
scoped_expr_caching m_scope1;
|
||||||
blastenv m_benv;
|
blastenv m_benv;
|
||||||
|
|
|
@ -120,8 +120,7 @@ void display_expr(expr const & e);
|
||||||
/** \brief Display message in the blast tactic diagnostic channel. */
|
/** \brief Display message in the blast tactic diagnostic channel. */
|
||||||
void display(char const * msg);
|
void display(char const * msg);
|
||||||
void display(sstream const & msg);
|
void display(sstream const & msg);
|
||||||
/**
|
/** \brief Create a local scope for saving the assignment and
|
||||||
\brief Create a local scope for saving the assignment and
|
|
||||||
metavariable declarations at curr_state() */
|
metavariable declarations at curr_state() */
|
||||||
class scope_assignment {
|
class scope_assignment {
|
||||||
bool m_keep;
|
bool m_keep;
|
||||||
|
@ -131,8 +130,17 @@ public:
|
||||||
void commit();
|
void commit();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Auxiliary object for setting thread local storage associated with blast tactic.
|
typedef std::function<bool(expr const &)> unfold_macro_pred;
|
||||||
|
/** \brief Auxiliary object used to temporarily set predicate used to decide
|
||||||
|
whether macros will be unfolded or not. */
|
||||||
|
class scope_unfold_macro_pred {
|
||||||
|
unfold_macro_pred m_old_pred;
|
||||||
|
public:
|
||||||
|
scope_unfold_macro_pred(unfold_macro_pred const & pred);
|
||||||
|
~scope_unfold_macro_pred();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Auxiliary object for setting thread local storage associated with blast tactic.
|
||||||
This is for debugging purposes only. It allow us to debug/test procedures that can
|
This is for debugging purposes only. It allow us to debug/test procedures that can
|
||||||
only be invoked from blast. */
|
only be invoked from blast. */
|
||||||
class scope_debug {
|
class scope_debug {
|
||||||
|
|
Loading…
Reference in a new issue