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:
Leonardo de Moura 2014-04-17 13:12:49 -07:00
parent 1fd5e9682d
commit 3712da0b54
4 changed files with 17 additions and 29 deletions

View file

@ -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); }

View file

@ -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);

View file

@ -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);
}

View file

@ -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;