diff --git a/src/library/blast/branch.cpp b/src/library/blast/branch.cpp index 2b339c808..d5cf5f7a1 100644 --- a/src/library/blast/branch.cpp +++ b/src/library/blast/branch.cpp @@ -27,7 +27,7 @@ struct hypothesis_depth_lt { } }; -void branch::get_sorted_hypotheses(hypothesis_idx_buffer & r) { +void branch::get_sorted_hypotheses(hypothesis_idx_buffer & r) const { m_context.for_each([&](unsigned hidx, hypothesis const &) { r.push_back(hidx); }); @@ -66,7 +66,7 @@ void branch::add_deps(expr const & e, hypothesis & h_user, unsigned hidx_user) { } return false; } else if (is_mref(l)) { - m_mvars.insert(mref_index(l)); + m_mvar_idxs.insert(mref_index(l)); return false; } else { return true; @@ -110,7 +110,7 @@ void branch::set_target(expr const & t) { m_target_deps.insert(lref_index(e)); return false; } else if (is_mref(e)) { - m_mvars.insert(mref_index(e)); + m_mvar_idxs.insert(mref_index(e)); return false; } else { return true; diff --git a/src/library/blast/branch.h b/src/library/blast/branch.h index 0797ccad4..7a63c1946 100644 --- a/src/library/blast/branch.h +++ b/src/library/blast/branch.h @@ -11,18 +11,20 @@ Author: Leonardo de Moura namespace lean { namespace blast { -typedef rb_tree metavar_set; +typedef rb_tree metavar_idx_set; +template +using metavar_idx_map = typename lean::rb_map; class branch { - typedef rb_map context; - typedef rb_map forward_deps; + typedef hypothesis_idx_map context; + typedef hypothesis_idx_map forward_deps; friend class state; unsigned m_next; context m_context; forward_deps m_forward_deps; // given an entry (h -> {h_1, ..., h_n}), we have that each h_i uses h. expr m_target; hypothesis_idx_set m_target_deps; - metavar_set m_mvars; + metavar_idx_set m_mvar_idxs; /** \brief Mark a hypothesis as fixed. The type/value of a fixed hypothesis cannot be modified. A hypothesis is fixed when it occurs in the type of some metavariable. */ @@ -39,7 +41,7 @@ class branch { public: branch():m_next(0) {} /** \brief Store in \c r the hypotheses in this branch sorted by depth */ - void get_sorted_hypotheses(hypothesis_idx_buffer & r); + void get_sorted_hypotheses(hypothesis_idx_buffer & r) const; expr add_hypothesis(name const & n, expr const & type, optional const & value, optional const & jst); expr add_hypothesis(expr const & type, optional const & value, optional const & jst); @@ -51,6 +53,8 @@ public: lean_assert(is_lref(e)); return get(lref_index(e)); } + + expr const & get_target() const { return m_target; } }; void initialize_branch(); diff --git a/src/library/blast/hypothesis.h b/src/library/blast/hypothesis.h index 61eeb0c93..90ed83dd5 100644 --- a/src/library/blast/hypothesis.h +++ b/src/library/blast/hypothesis.h @@ -6,7 +6,7 @@ Author: Leonardo de Moura */ #pragma once #include "util/rc.h" -#include "util/rb_tree.h" +#include "util/rb_map.h" #include "kernel/expr.h" namespace lean { @@ -18,6 +18,8 @@ class state; typedef rb_tree hypothesis_idx_set; typedef list hypothesis_idx_list; typedef buffer hypothesis_idx_buffer; +template +using hypothesis_idx_map = typename lean::rb_map; class hypothesis { friend class branch; @@ -31,6 +33,7 @@ class hypothesis { optional m_justification; public: hypothesis():m_active(true), m_fixed(false), m_depth(0) {} + name const & get_name() const { return m_name; } bool is_active() const { return m_active; } unsigned get_depth() const { return m_depth; } hypothesis_idx_set const & get_backward_deps() const { return m_deps; } diff --git a/src/library/blast/state.cpp b/src/library/blast/state.cpp index 637ca2100..0f85dc1ea 100644 --- a/src/library/blast/state.cpp +++ b/src/library/blast/state.cpp @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ +#include "kernel/abstract.h" #include "kernel/for_each_fn.h" #include "library/blast/state.h" @@ -34,6 +35,62 @@ expr state::mk_metavar(hypothesis_idx_buffer const & ctx, expr const & type) { expr state::mk_metavar(expr const & type) { hypothesis_idx_buffer ctx; m_main.get_sorted_hypotheses(ctx); - return mk_metavar(ctx, type); + return state::mk_metavar(ctx, type); +} + +goal state::to_goal(branch const & b) const { + hypothesis_idx_map hidx2local; + metavar_idx_map midx2meta; + name M("M"); + std::function convert = [&](expr const & e) { + return replace(e, [&](expr const & e) { + if (is_lref(e)) { + auto r = hidx2local.find(lref_index(e)); + lean_assert(r); + return some_expr(*r); + } else if (is_mref(e)) { + auto r = midx2meta.find(mref_index(e)); + if (r) { + return some_expr(*r); + } else { + metavar_decl const * decl = m_metavar_decls.find(mref_index(e)); + lean_assert(decl); + buffer ctx; + for (unsigned hidx : decl->get_context()) { + ctx.push_back(*hidx2local.find(hidx)); + } + expr type = convert(decl->get_type()); + expr new_type = Pi(ctx, type); + expr new_mvar = lean::mk_metavar(name(M, mref_index(e)), new_type); + expr new_meta = mk_app(new_mvar, ctx); + midx2meta.insert(mref_index(e), new_meta); + return some_expr(new_meta); + } + } else { + return none_expr(); + } + }); + }; + name H("H"); + hypothesis_idx_buffer hidxs; + b.get_sorted_hypotheses(hidxs); + buffer hyps; + for (unsigned hidx : hidxs) { + hypothesis const * h = b.get(hidx); + lean_assert(h); + // after we add support for let-decls in goals, we must convert back h->get_value() if it is available + expr new_h = lean::mk_local(h->get_name(), name(H, hidx), convert(h->get_type()), binder_info()); + hidx2local.insert(hidx, new_h); + hyps.push_back(new_h); + } + expr new_target = convert(b.get_target()); + expr new_mvar_type = Pi(hyps, new_target); + expr new_mvar = lean::mk_metavar(M, new_mvar_type); + expr new_meta = mk_app(new_mvar, hyps); + return goal(new_meta, new_target); +} + +goal state::to_goal() const { + return to_goal(m_main); } }} diff --git a/src/library/blast/state.h b/src/library/blast/state.h index f9aac5421..4f2f96a86 100644 --- a/src/library/blast/state.h +++ b/src/library/blast/state.h @@ -7,6 +7,7 @@ Author: Leonardo de Moura #pragma once #include "util/rb_map.h" #include "kernel/expr.h" +#include "library/tactic/goal.h" #include "library/blast/hypothesis.h" #include "library/blast/branch.h" @@ -20,18 +21,21 @@ public: metavar_decl() {} metavar_decl(hypothesis_idx_list const & c, hypothesis_idx_set const & s, expr const & t): m_context(c), m_context_as_set(s), m_type(t) {} + hypothesis_idx_list get_context() const { return m_context; } + expr const & get_type() const { return m_type; } }; class state { friend class context; - unsigned m_next_mref_index; - typedef rb_map metavar_decls; - typedef rb_map assignment; + typedef metavar_idx_map metavar_decls; + typedef metavar_idx_map assignment; + unsigned m_next_mref_index; metavar_decls m_metavar_decls; assignment m_assignment; branch m_main; unsigned add_metavar_decl(metavar_decl const & decl); + goal to_goal(branch const &) const; public: state(); @@ -61,5 +65,10 @@ public: metavar_decl const * get_metavar_decl(unsigned idx) const { return m_metavar_decls.find(idx); } metavar_decl const * get_metavar_decl(expr const & e) const { return get_metavar_decl(mref_index(e)); } + + /** \brief Convert main branch to a goal. + This is mainly used for pretty printing. However, in the future, we may use this capability + to invoke the tactic framework from the blast tactic. */ + goal to_goal() const; }; }}