2015-09-16 14:49:39 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2015-09-29 01:28:11 +00:00
|
|
|
#include "kernel/abstract.h"
|
2015-09-28 23:40:19 +00:00
|
|
|
#include "kernel/for_each_fn.h"
|
2015-09-29 17:42:00 +00:00
|
|
|
#include "kernel/replace_fn.h"
|
2015-09-16 14:49:39 +00:00
|
|
|
#include "library/blast/state.h"
|
2015-09-25 21:43:42 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
namespace blast {
|
2015-10-02 20:11:17 +00:00
|
|
|
state::state():m_next_uvar_index(0), m_next_mref_index(0) {}
|
2015-09-28 23:40:19 +00:00
|
|
|
|
2015-09-29 21:08:14 +00:00
|
|
|
/** \brief Mark that hypothesis h with index hidx is fixed by the meta-variable midx.
|
|
|
|
That is, `h` occurs in the type of `midx`. */
|
|
|
|
void state::add_fixed_by(unsigned hidx, unsigned midx) {
|
|
|
|
if (auto s = m_fixed_by.find(hidx)) {
|
|
|
|
if (!s->contains(midx)) {
|
|
|
|
metavar_idx_set new_s(*s);
|
|
|
|
new_s.insert(midx);
|
|
|
|
m_fixed_by.insert(hidx, new_s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
metavar_idx_set new_s;
|
|
|
|
new_s.insert(midx);
|
|
|
|
m_fixed_by.insert(hidx, new_s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-28 23:40:19 +00:00
|
|
|
expr state::mk_metavar(hypothesis_idx_buffer const & ctx, expr const & type) {
|
|
|
|
hypothesis_idx_set ctx_as_set;
|
|
|
|
for (unsigned const & hidx : ctx)
|
|
|
|
ctx_as_set.insert(hidx);
|
2015-09-29 21:08:14 +00:00
|
|
|
unsigned midx = m_next_mref_index;
|
2015-09-28 23:40:19 +00:00
|
|
|
for_each(type, [&](expr const & e, unsigned) {
|
2015-09-29 19:13:20 +00:00
|
|
|
if (!has_href(e))
|
2015-09-28 23:40:19 +00:00
|
|
|
return false;
|
2015-09-29 19:13:20 +00:00
|
|
|
if (is_href(e)) {
|
|
|
|
lean_assert(ctx_as_set.contains(href_index(e)));
|
2015-09-29 21:08:14 +00:00
|
|
|
add_fixed_by(href_index(e), midx);
|
2015-09-28 23:40:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true; // continue search
|
|
|
|
});
|
2015-09-25 21:43:42 +00:00
|
|
|
m_next_mref_index++;
|
2015-09-29 21:08:14 +00:00
|
|
|
m_metavar_decls.insert(midx, metavar_decl(to_list(ctx), ctx_as_set, type));
|
|
|
|
return blast::mk_mref(midx);
|
2015-09-28 23:40:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
expr state::mk_metavar(expr const & type) {
|
|
|
|
hypothesis_idx_buffer ctx;
|
|
|
|
m_main.get_sorted_hypotheses(ctx);
|
2015-09-29 01:28:11 +00:00
|
|
|
return state::mk_metavar(ctx, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
goal state::to_goal(branch const & b) const {
|
|
|
|
hypothesis_idx_map<expr> hidx2local;
|
|
|
|
metavar_idx_map<expr> midx2meta;
|
|
|
|
name M("M");
|
|
|
|
std::function<expr(expr const &)> convert = [&](expr const & e) {
|
2015-09-29 17:42:00 +00:00
|
|
|
return lean::replace(e, [&](expr const & e) {
|
2015-09-29 19:13:20 +00:00
|
|
|
if (is_href(e)) {
|
|
|
|
auto r = hidx2local.find(href_index(e));
|
2015-09-29 01:28:11 +00:00
|
|
|
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<expr> 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<expr> 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
|
2015-09-29 17:04:11 +00:00
|
|
|
expr new_h = lean::mk_local(name(H, hidx), h->get_name(), convert(h->get_type()), binder_info());
|
2015-09-29 01:28:11 +00:00
|
|
|
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);
|
2015-09-25 21:43:42 +00:00
|
|
|
}
|
2015-09-29 01:55:24 +00:00
|
|
|
|
2015-09-29 17:04:11 +00:00
|
|
|
void state::display(environment const & env, io_state const & ios) const {
|
|
|
|
formatter fmt = ios.get_formatter_factory()(env, ios.get_options());
|
|
|
|
ios.get_diagnostic_channel() << mk_pair(to_goal().pp(fmt), ios.get_options());
|
|
|
|
}
|
|
|
|
|
2015-09-29 01:55:24 +00:00
|
|
|
#ifdef LEAN_DEBUG
|
2015-09-29 19:42:20 +00:00
|
|
|
bool state::check_hypothesis(expr const & e, branch const & b, unsigned hidx, hypothesis const & h) const {
|
|
|
|
lean_assert(closed(e));
|
2015-09-29 01:55:24 +00:00
|
|
|
for_each(e, [&](expr const & n, unsigned) {
|
2015-09-29 19:31:54 +00:00
|
|
|
lean_assert(!blast::is_local(n));
|
2015-09-29 19:13:20 +00:00
|
|
|
if (is_href(n)) {
|
2015-09-29 01:55:24 +00:00
|
|
|
lean_assert(h.depends_on(n));
|
2015-09-29 19:13:20 +00:00
|
|
|
lean_assert(b.hidx_depends_on(hidx, href_index(n)));
|
2015-09-29 01:55:24 +00:00
|
|
|
} else if (is_mref(n)) {
|
|
|
|
// metavariable is in the set of used metavariables
|
|
|
|
lean_assert(b.has_mvar(n));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-29 19:42:20 +00:00
|
|
|
bool state::check_hypothesis(branch const & b, unsigned hidx, hypothesis const & h) const {
|
|
|
|
lean_assert(check_hypothesis(h.get_type(), b, hidx, h));
|
|
|
|
lean_assert(!h.get_value() || check_hypothesis(*h.get_value(), b, hidx, h));
|
2015-09-29 01:55:24 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-29 19:42:20 +00:00
|
|
|
bool state::check_target(branch const & b) const {
|
|
|
|
lean_assert(closed(b.get_target()));
|
2015-09-29 01:55:24 +00:00
|
|
|
for_each(b.get_target(), [&](expr const & n, unsigned) {
|
2015-09-29 19:31:54 +00:00
|
|
|
lean_assert(!blast::is_local(n));
|
2015-09-29 19:13:20 +00:00
|
|
|
if (is_href(n)) {
|
2015-09-29 01:55:24 +00:00
|
|
|
lean_assert(b.target_depends_on(n));
|
|
|
|
} else if (is_mref(n)) {
|
|
|
|
// metavariable is in the set of used metavariables
|
|
|
|
lean_assert(b.has_mvar(n));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-29 19:42:20 +00:00
|
|
|
bool state::check_invariant(branch const & b) const {
|
|
|
|
b.for_each_hypothesis([&](unsigned hidx, hypothesis const & h) {
|
|
|
|
lean_assert(check_hypothesis(b, hidx, h));
|
|
|
|
});
|
|
|
|
lean_assert(check_target(b));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-29 01:55:24 +00:00
|
|
|
bool state::check_invariant() const {
|
|
|
|
return check_invariant(m_main);
|
|
|
|
}
|
|
|
|
#endif
|
2015-09-25 21:43:42 +00:00
|
|
|
}}
|