2014-02-22 01:55:59 +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
|
|
|
|
*/
|
2014-02-22 16:41:45 +00:00
|
|
|
#include <utility>
|
|
|
|
#include "kernel/metavar.h"
|
2014-02-22 19:44:57 +00:00
|
|
|
#include "kernel/free_vars.h"
|
|
|
|
#include "kernel/replace_visitor.h"
|
|
|
|
#include "kernel/justification.h"
|
|
|
|
#include "kernel/instantiate.h"
|
2014-02-23 00:12:06 +00:00
|
|
|
#include "kernel/find_fn.h"
|
2014-02-22 01:55:59 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2014-02-22 16:41:45 +00:00
|
|
|
bool substitution::is_assigned(name const & m) const {
|
|
|
|
return m_subst.contains(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<std::pair<expr, justification>> substitution::get_assignment(name const & m) const {
|
|
|
|
auto it = m_subst.find(m);
|
|
|
|
if (it)
|
|
|
|
return optional<std::pair<expr, justification>>(*it);
|
|
|
|
else
|
|
|
|
return optional<std::pair<expr, justification>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<expr> substitution::get_expr(name const & m) const {
|
|
|
|
auto it = m_subst.find(m);
|
|
|
|
if (it)
|
|
|
|
return some_expr(it->first);
|
|
|
|
else
|
|
|
|
return none_expr();
|
|
|
|
}
|
2014-02-22 01:55:59 +00:00
|
|
|
|
2014-02-22 16:41:45 +00:00
|
|
|
void substitution::assign(name const & m, expr const & t, justification const & j) {
|
2014-02-22 19:44:57 +00:00
|
|
|
lean_assert(closed(t));
|
2014-02-22 16:41:45 +00:00
|
|
|
m_subst.insert(m, mk_pair(t, j));
|
|
|
|
}
|
|
|
|
|
|
|
|
void substitution::assign(name const & m, expr const & t) {
|
|
|
|
assign(m, t, justification());
|
|
|
|
}
|
|
|
|
|
2014-02-23 00:12:06 +00:00
|
|
|
void substitution::for_each(std::function<void(name const & n, expr const & e, justification const & j)> const & fn) const {
|
2014-02-22 16:41:45 +00:00
|
|
|
m_subst.for_each([=](name const & n, std::pair<expr, justification> const & a) {
|
|
|
|
fn(n, a.first, a.second);
|
|
|
|
});
|
|
|
|
}
|
2014-02-22 19:44:57 +00:00
|
|
|
|
|
|
|
class instantiate_metavars_fn : public replace_visitor {
|
|
|
|
protected:
|
|
|
|
substitution & m_subst;
|
|
|
|
justification m_jst;
|
|
|
|
bool m_use_jst;
|
|
|
|
bool m_update;
|
|
|
|
|
|
|
|
void save_jst(justification const & j) { m_jst = mk_composite1(m_jst, j); }
|
|
|
|
|
|
|
|
virtual expr visit_meta(expr const & m, context const &) {
|
|
|
|
name const & m_name = mlocal_name(m);
|
|
|
|
auto p1 = m_subst.get_assignment(m_name);
|
|
|
|
if (p1) {
|
|
|
|
if (!has_metavar(p1->first)) {
|
|
|
|
if (m_use_jst)
|
|
|
|
save_jst(p1->second);
|
|
|
|
return p1->first;
|
|
|
|
} else if (m_use_jst) {
|
|
|
|
if (m_update) {
|
2014-02-23 00:12:06 +00:00
|
|
|
auto p2 = m_subst.d_instantiate_metavars(p1->first);
|
2014-02-22 19:44:57 +00:00
|
|
|
justification new_jst = mk_composite1(p1->second, p2.second);
|
|
|
|
m_subst.assign(m_name, p2.first, new_jst);
|
|
|
|
save_jst(new_jst);
|
|
|
|
return p2.first;
|
|
|
|
} else {
|
2014-02-23 00:12:06 +00:00
|
|
|
auto p2 = m_subst.instantiate_metavars(p1->first);
|
2014-02-22 19:44:57 +00:00
|
|
|
save_jst(mk_composite1(p1->second, p2.second));
|
|
|
|
return p2.first;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (m_update) {
|
2014-02-23 00:12:06 +00:00
|
|
|
expr r = m_subst.d_instantiate_metavars_wo_jst(p1->first);
|
2014-02-22 19:44:57 +00:00
|
|
|
m_subst.assign(m_name, r);
|
|
|
|
return r;
|
|
|
|
} else {
|
2014-02-23 00:12:06 +00:00
|
|
|
return m_subst.instantiate_metavars_wo_jst(p1->first);
|
2014-02-22 19:44:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual expr visit_app(expr const & e, context const & ctx) {
|
|
|
|
buffer<expr> args;
|
|
|
|
expr const * it = &e;
|
|
|
|
while (is_app(*it)) {
|
|
|
|
args.push_back(visit(app_arg(*it), ctx));
|
|
|
|
it = &app_fn(*it);
|
|
|
|
}
|
|
|
|
expr const & f = *it;
|
|
|
|
if (is_metavar(f) && m_subst.is_assigned(mlocal_name(f))) {
|
|
|
|
expr new_f = visit_meta(f, ctx);
|
|
|
|
return apply_beta(new_f, args.size(), args.data());
|
|
|
|
} else {
|
|
|
|
args.push_back(visit(f, ctx));
|
|
|
|
return update_rev_app(e, args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
instantiate_metavars_fn(substitution & s, bool use_jst, bool updt):
|
|
|
|
m_subst(s), m_use_jst(use_jst), m_update(updt) {}
|
|
|
|
justification const & get_justification() const { return m_jst; }
|
|
|
|
};
|
|
|
|
|
2014-02-23 00:12:06 +00:00
|
|
|
std::pair<expr, justification> substitution::instantiate_metavars(expr const & e) const {
|
|
|
|
instantiate_metavars_fn fn(const_cast<substitution&>(*this), true, false);
|
2014-02-22 19:44:57 +00:00
|
|
|
expr r = fn(e);
|
|
|
|
return mk_pair(r, fn.get_justification());
|
|
|
|
}
|
|
|
|
|
2014-02-23 00:12:06 +00:00
|
|
|
std::pair<expr, justification> substitution::d_instantiate_metavars(expr const & e) {
|
|
|
|
instantiate_metavars_fn fn(*this, true, true);
|
2014-02-22 19:44:57 +00:00
|
|
|
expr r = fn(e);
|
|
|
|
return mk_pair(r, fn.get_justification());
|
|
|
|
}
|
|
|
|
|
2014-02-23 00:12:06 +00:00
|
|
|
expr substitution::instantiate_metavars_wo_jst(expr const & e) const {
|
|
|
|
return instantiate_metavars_fn(const_cast<substitution&>(*this), false, false)(e);
|
2014-02-22 19:44:57 +00:00
|
|
|
}
|
|
|
|
|
2014-02-23 00:12:06 +00:00
|
|
|
expr substitution::d_instantiate_metavars_wo_jst(expr const & e) {
|
|
|
|
return instantiate_metavars_fn(*this, false, true)(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool substitution::occurs(name const & m, expr const & e) const {
|
|
|
|
if (!has_metavar(e))
|
|
|
|
return false;
|
|
|
|
auto it = find(e, [&](expr const & e, unsigned) {
|
|
|
|
if (is_metavar(e)) {
|
|
|
|
if (mlocal_name(e) == m)
|
|
|
|
return true;
|
|
|
|
auto s = get_expr(e);
|
|
|
|
return s && occurs(m, *s);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return static_cast<bool>(it);
|
2014-02-22 19:44:57 +00:00
|
|
|
}
|
2014-02-22 01:55:59 +00:00
|
|
|
}
|