2014-09-10 17:24:35 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#include "kernel/abstract.h"
|
2014-09-25 15:13:27 +00:00
|
|
|
#include "kernel/replace_fn.h"
|
2014-11-24 00:11:50 +00:00
|
|
|
#include "kernel/metavar.h"
|
2014-12-10 20:43:32 +00:00
|
|
|
#include "library/local_context.h"
|
2014-09-10 17:24:35 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2014-09-25 15:13:27 +00:00
|
|
|
/** \brief Given a list of local constants \c locals
|
|
|
|
(x_n : A_n) ... (x_0 : A_0)
|
|
|
|
and a term \c e
|
|
|
|
t[x_0, ..., x_n]
|
|
|
|
return
|
|
|
|
t[#n, ..., #0]
|
|
|
|
*/
|
2015-06-18 22:41:00 +00:00
|
|
|
expr local_context::abstract_locals(expr const & e, list<expr> const & locals) {
|
2014-09-25 15:13:27 +00:00
|
|
|
lean_assert(std::all_of(locals.begin(), locals.end(), [](expr const & e) { return closed(e) && is_local(e); }));
|
|
|
|
if (!has_local(e))
|
|
|
|
return e;
|
|
|
|
return replace(e, [=](expr const & m, unsigned offset) -> optional<expr> {
|
|
|
|
if (!has_local(m))
|
|
|
|
return some_expr(m); // expression m does not contain local constants
|
|
|
|
if (is_local(m)) {
|
|
|
|
unsigned i = 0;
|
|
|
|
for (expr const & l : locals) {
|
|
|
|
if (mlocal_name(l) == mlocal_name(m))
|
|
|
|
return some_expr(copy_tag(m, mk_var(offset + i)));
|
|
|
|
i++;
|
|
|
|
}
|
2015-06-18 22:41:00 +00:00
|
|
|
return some_expr(m);
|
2014-09-25 15:13:27 +00:00
|
|
|
}
|
|
|
|
return none_expr();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-06-18 22:41:00 +00:00
|
|
|
auto local_context::to_local_decl(expr const & l, list<expr> const & ctx) -> local_decl {
|
|
|
|
return local_decl(local_pp_name(l), abstract_locals(mlocal_type(l), ctx), local_info(l));
|
|
|
|
}
|
|
|
|
|
2014-09-25 16:44:34 +00:00
|
|
|
local_context::local_context() {}
|
|
|
|
local_context::local_context(list<expr> const & ctx) {
|
2014-09-10 19:49:35 +00:00
|
|
|
set_ctx(ctx);
|
|
|
|
}
|
2014-09-10 17:24:35 +00:00
|
|
|
|
|
|
|
void local_context::set_ctx(list<expr> const & ctx) {
|
|
|
|
m_ctx = ctx;
|
2015-06-18 22:41:00 +00:00
|
|
|
buffer<local_decl> tmp;
|
2014-09-25 15:13:27 +00:00
|
|
|
list<expr> it = ctx;
|
|
|
|
while (it) {
|
2015-06-18 22:41:00 +00:00
|
|
|
tmp.push_back(to_local_decl(head(it), tail(it)));
|
2014-09-25 15:13:27 +00:00
|
|
|
it = tail(it);
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
2014-09-25 15:13:27 +00:00
|
|
|
m_ctx_abstracted = to_list(tmp.begin(), tmp.end());
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
|
|
|
|
2014-09-10 19:49:35 +00:00
|
|
|
expr local_context::pi_abstract_context(expr e, tag g) const {
|
2014-09-25 15:13:27 +00:00
|
|
|
e = abstract_locals(e, m_ctx);
|
2015-06-18 22:41:00 +00:00
|
|
|
for (local_decl const & l : m_ctx_abstracted)
|
|
|
|
e = mk_pi(std::get<0>(l), std::get<1>(l), e, std::get<2>(l), g);
|
2014-09-10 17:24:35 +00:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2014-09-25 15:13:27 +00:00
|
|
|
static expr apply_context_core(expr const & f, list<expr> const & ctx, tag g) {
|
|
|
|
if (ctx)
|
2014-10-15 20:17:09 +00:00
|
|
|
return mk_app(apply_context_core(f, tail(ctx), g), head(ctx), g);
|
2014-09-25 15:13:27 +00:00
|
|
|
else
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2014-09-10 19:49:35 +00:00
|
|
|
expr local_context::apply_context(expr const & f, tag g) const {
|
2014-09-25 15:13:27 +00:00
|
|
|
return apply_context_core(f, m_ctx, g);
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
|
|
|
|
2014-11-05 02:37:31 +00:00
|
|
|
expr local_context::mk_type_metavar(name_generator & ngen, tag g) const {
|
2014-09-25 16:44:34 +00:00
|
|
|
name n = ngen.next();
|
2014-10-15 20:17:09 +00:00
|
|
|
expr s = mk_sort(mk_meta_univ(ngen.next()), g);
|
2014-09-10 17:24:35 +00:00
|
|
|
expr t = pi_abstract_context(s, g);
|
2014-10-15 20:17:09 +00:00
|
|
|
return ::lean::mk_metavar(n, t, g);
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
|
|
|
|
2014-11-05 02:37:31 +00:00
|
|
|
expr local_context::mk_type_meta(name_generator & ngen, tag g) const {
|
2014-09-25 16:44:34 +00:00
|
|
|
return apply_context(mk_type_metavar(ngen, g), g);
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
|
|
|
|
2014-11-05 02:37:31 +00:00
|
|
|
expr local_context::mk_metavar(name_generator & ngen, optional<name> const & suffix, optional<expr> const & type, tag g) const {
|
2014-09-25 16:44:34 +00:00
|
|
|
name n = ngen.next();
|
2014-10-30 19:45:41 +00:00
|
|
|
if (suffix)
|
|
|
|
n = n + *suffix;
|
2014-09-25 16:44:34 +00:00
|
|
|
expr r_type = type ? *type : mk_type_meta(ngen, g);
|
2014-09-10 17:24:35 +00:00
|
|
|
expr t = pi_abstract_context(r_type, g);
|
2014-10-15 20:17:09 +00:00
|
|
|
return ::lean::mk_metavar(n, t, g);
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
|
|
|
|
2014-11-05 02:37:31 +00:00
|
|
|
expr local_context::mk_meta(name_generator & ngen, optional<name> const & suffix, optional<expr> const & type, tag g) const {
|
2014-10-30 19:45:41 +00:00
|
|
|
expr mvar = mk_metavar(ngen, suffix, type, g);
|
2014-09-10 17:24:35 +00:00
|
|
|
expr meta = apply_context(mvar, g);
|
|
|
|
return meta;
|
|
|
|
}
|
|
|
|
|
|
|
|
void local_context::add_local(expr const & l) {
|
2014-09-25 15:13:27 +00:00
|
|
|
lean_assert(is_local(l));
|
2015-06-18 22:41:00 +00:00
|
|
|
m_ctx_abstracted = cons(to_local_decl(l, m_ctx), m_ctx_abstracted);
|
2014-09-25 15:13:27 +00:00
|
|
|
m_ctx = cons(l, m_ctx);
|
|
|
|
lean_assert(length(m_ctx) == length(m_ctx_abstracted));
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
list<expr> const & local_context::get_data() const {
|
|
|
|
return m_ctx;
|
|
|
|
}
|
2014-11-24 00:11:50 +00:00
|
|
|
|
|
|
|
static list<expr> instantiate_locals(list<expr> const & ls, substitution & s) {
|
|
|
|
return map(ls, [&](expr const & l) { return update_mlocal(l, s.instantiate(mlocal_type(l))); });
|
|
|
|
}
|
|
|
|
|
|
|
|
local_context local_context::instantiate(substitution s) const {
|
|
|
|
return local_context(instantiate_locals(m_ctx, s));
|
|
|
|
}
|
2014-09-10 17:24:35 +00:00
|
|
|
}
|