refactor(kernel/instantiate): use get_free_var_range to improve instantiate, remove instantiate_with_closed, fix index overflow bug
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
1fd5e9682d
commit
3712da0b54
4 changed files with 17 additions and 29 deletions
|
@ -11,17 +11,21 @@ Author: Leonardo de Moura
|
|||
#include "kernel/instantiate.h"
|
||||
|
||||
namespace lean {
|
||||
template<bool ClosedSubst>
|
||||
expr instantiate_core(expr const & a, unsigned s, unsigned n, expr const * subst) {
|
||||
expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
|
||||
if (s >= get_free_var_range(a))
|
||||
return a;
|
||||
return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
|
||||
unsigned s1 = s + offset;
|
||||
if (s1 < s)
|
||||
return some_expr(m); // overflow, vidx can't be >= max unsigned
|
||||
if (s1 >= get_free_var_range(m))
|
||||
return some_expr(m); // expression m does not contain free variables with idx >= s1
|
||||
if (is_var(m)) {
|
||||
unsigned vidx = var_idx(m);
|
||||
if (vidx >= offset + s) {
|
||||
if (vidx < offset + s + n) {
|
||||
if (ClosedSubst)
|
||||
return some_expr(subst[vidx - s - offset]);
|
||||
else
|
||||
return some_expr(lift_free_vars(subst[vidx - s - offset], offset));
|
||||
if (vidx >= s1) {
|
||||
unsigned h = s1 + n;
|
||||
if (h < s1 /* overflow, h is bigger than any vidx */ || vidx < h) {
|
||||
return some_expr(lift_free_vars(subst[vidx - s1], offset));
|
||||
} else {
|
||||
return some_expr(mk_var(vidx - n));
|
||||
}
|
||||
|
@ -31,11 +35,6 @@ expr instantiate_core(expr const & a, unsigned s, unsigned n, expr const * subst
|
|||
});
|
||||
}
|
||||
|
||||
expr instantiate_with_closed(expr const & e, unsigned s, unsigned n, expr const * subst) { return instantiate_core<true>(e, s, n, subst); }
|
||||
expr instantiate_with_closed(expr const & e, unsigned n, expr const * s) { return instantiate_with_closed(e, 0, n, s); }
|
||||
expr instantiate_with_closed(expr const & e, std::initializer_list<expr> const & l) { return instantiate_with_closed(e, l.size(), l.begin()); }
|
||||
expr instantiate_with_closed(expr const & e, expr const & s) { return instantiate_with_closed(e, 1, &s); }
|
||||
expr instantiate(expr const & e, unsigned s, unsigned n, expr const * subst) { return instantiate_core<false>(e, s, n, subst); }
|
||||
expr instantiate(expr const & e, unsigned n, expr const * s) { return instantiate(e, 0, n, s); }
|
||||
expr instantiate(expr const & e, std::initializer_list<expr> const & l) { return instantiate(e, l.size(), l.begin()); }
|
||||
expr instantiate(expr const & e, unsigned i, expr const & s) { return instantiate(e, i, 1, &s); }
|
||||
|
|
|
@ -9,15 +9,6 @@ Author: Leonardo de Moura
|
|||
|
||||
namespace lean {
|
||||
class ro_metavar_env;
|
||||
/**
|
||||
\brief Replace the free variables with indices 0, ..., n-1 with s[0], ..., s[n-1] in e.
|
||||
|
||||
\pre s[0], ..., s[n-1] must be closed expressions (i.e., no free variables).
|
||||
*/
|
||||
expr instantiate_with_closed(expr const & e, unsigned n, expr const * s);
|
||||
expr instantiate_with_closed(expr const & e, std::initializer_list<expr> const & l);
|
||||
expr instantiate_with_closed(expr const & e, expr const & s);
|
||||
|
||||
/** \brief Replace the free variables with indices 0, ..., n-1 with s[0], ..., s[n-1] in e. */
|
||||
expr instantiate(expr const & e, unsigned n, expr const * s);
|
||||
expr instantiate(expr const & e, std::initializer_list<expr> const & l);
|
||||
|
|
|
@ -23,8 +23,6 @@ expr pi_body_at(expr const & pi, expr const & a) {
|
|||
lean_assert(is_pi(pi));
|
||||
if (closed(binder_body(pi)))
|
||||
return binder_body(pi);
|
||||
else if (closed(a))
|
||||
return instantiate_with_closed(binder_body(pi), a);
|
||||
else
|
||||
return instantiate(binder_body(pi), a);
|
||||
}
|
||||
|
|
|
@ -31,12 +31,12 @@ static void tst1() {
|
|||
|
||||
static void tst2() {
|
||||
expr r = mk_lambda("x", Type, mk_app({Var(0), Var(1), Var(2)}));
|
||||
std::cout << instantiate_with_closed(r, Const("a")) << std::endl;
|
||||
lean_assert(instantiate_with_closed(r, Const("a")) == mk_lambda("x", Type, mk_app({Var(0), Const("a"), Var(1)})));
|
||||
lean_assert(instantiate_with_closed(instantiate_with_closed(r, Const("a")), Const("b")) ==
|
||||
std::cout << instantiate(r, Const("a")) << std::endl;
|
||||
lean_assert(instantiate(r, Const("a")) == mk_lambda("x", Type, mk_app({Var(0), Const("a"), Var(1)})));
|
||||
lean_assert(instantiate(instantiate(r, Const("a")), Const("b")) ==
|
||||
mk_lambda("x", Type, mk_app({Var(0), Const("a"), Const("b")})));
|
||||
std::cout << instantiate_with_closed(binder_body(r), Const("a")) << std::endl;
|
||||
lean_assert(instantiate_with_closed(binder_body(r), Const("a")) == mk_app({Const("a"), Var(0), Var(1)}));
|
||||
std::cout << instantiate(binder_body(r), Const("a")) << std::endl;
|
||||
lean_assert(instantiate(binder_body(r), Const("a")) == mk_app({Const("a"), Var(0), Var(1)}));
|
||||
std::cout << instantiate(r, Var(10)) << std::endl;
|
||||
lean_assert(instantiate(r, Var(10)) == mk_lambda("x", Type, mk_app({Var(0), Var(11), Var(1)})));
|
||||
std::cout << mk_pi("_", Var(3), Var(4)) << std::endl;
|
||||
|
|
Loading…
Reference in a new issue