2015-06-01 22:15:37 +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
|
|
|
|
*/
|
|
|
|
#include <string>
|
|
|
|
#include "kernel/instantiate.h"
|
2015-06-02 00:53:25 +00:00
|
|
|
#include "kernel/error_msgs.h"
|
2015-06-01 22:15:37 +00:00
|
|
|
#include "library/scoped_ext.h"
|
|
|
|
#include "library/expr_pair.h"
|
|
|
|
#include "library/relation_manager.h"
|
|
|
|
#include "library/simplifier/ceqv.h"
|
2015-07-22 17:39:30 +00:00
|
|
|
#include "library/simplifier/simp_rule_set.h"
|
2015-06-01 22:15:37 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2015-07-22 17:39:30 +00:00
|
|
|
bool operator==(simp_rule const & r1, simp_rule const & r2) {
|
2015-06-01 22:15:37 +00:00
|
|
|
return r1.m_lhs == r2.m_lhs && r1.m_rhs == r2.m_rhs;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule::simp_rule(name const & id, levels const & univ_metas, list<expr> const & metas,
|
|
|
|
expr const & lhs, expr const & rhs, expr const & proof, bool is_perm):
|
2015-06-02 00:53:25 +00:00
|
|
|
m_id(id), m_univ_metas(univ_metas), m_metas(metas), m_lhs(lhs), m_rhs(rhs), m_proof(proof),
|
2015-06-01 22:15:37 +00:00
|
|
|
m_is_permutation(is_perm) {}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
format simp_rule::pp(formatter const & fmt) const {
|
2015-06-02 00:53:25 +00:00
|
|
|
format r;
|
|
|
|
r += format("#") + format(length(m_metas));
|
|
|
|
if (m_is_permutation)
|
|
|
|
r += space() + format("perm");
|
2015-06-02 05:23:34 +00:00
|
|
|
format r1 = comma() + space() + fmt(m_lhs);
|
|
|
|
r1 += space() + format("↦") + pp_indent_expr(fmt, m_rhs);
|
|
|
|
r += group(r1);
|
2015-06-02 00:53:25 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_set::simp_rule_set(name const & eqv):
|
2015-06-01 22:15:37 +00:00
|
|
|
m_eqv(eqv) {}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_set::insert(simp_rule const & r) {
|
2015-06-01 22:15:37 +00:00
|
|
|
m_set.insert(r.get_lhs(), r);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
list<simp_rule> const * simp_rule_set::find(head_index const & h) const {
|
2015-06-01 22:15:37 +00:00
|
|
|
return m_set.find(h);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_set::for_each(std::function<void(simp_rule const &)> const & fn) const {
|
|
|
|
m_set.for_each_entry([&](head_index const &, simp_rule const & r) { fn(r); });
|
2015-06-01 22:15:37 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_set::erase(simp_rule const & r) {
|
2015-06-01 22:15:37 +00:00
|
|
|
m_set.erase(r.get_lhs(), r);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_sets::insert(name const & eqv, simp_rule const & r) {
|
|
|
|
simp_rule_set s(eqv);
|
2015-06-01 22:15:37 +00:00
|
|
|
if (auto const * curr = m_sets.find(eqv)) {
|
|
|
|
s = *curr;
|
|
|
|
}
|
|
|
|
s.insert(r);
|
|
|
|
m_sets.insert(eqv, s);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_sets::erase(name const & eqv, simp_rule const & r) {
|
2015-06-01 22:15:37 +00:00
|
|
|
if (auto const * curr = m_sets.find(eqv)) {
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_set s = *curr;
|
2015-06-01 22:15:37 +00:00
|
|
|
s.erase(r);
|
|
|
|
if (s.empty())
|
|
|
|
m_sets.erase(eqv);
|
|
|
|
else
|
|
|
|
m_sets.insert(eqv, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_sets::get_relations(buffer<name> & rs) const {
|
|
|
|
m_sets.for_each([&](name const & r, simp_rule_set const &) {
|
2015-06-01 22:15:37 +00:00
|
|
|
rs.push_back(r);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_set const * simp_rule_sets::find(name const & eqv) const {
|
2015-06-01 22:15:37 +00:00
|
|
|
return m_sets.find(eqv);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
list<simp_rule> const * simp_rule_sets::find(name const & eqv, head_index const & h) const {
|
2015-06-01 22:15:37 +00:00
|
|
|
if (auto const * s = m_sets.find(eqv))
|
|
|
|
return s->find(h);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void simp_rule_sets::for_each(std::function<void(name const &, simp_rule const &)> const & fn) const {
|
|
|
|
m_sets.for_each([&](name const & eqv, simp_rule_set const & s) {
|
|
|
|
s.for_each([&](simp_rule const & r) {
|
2015-06-01 22:15:37 +00:00
|
|
|
fn(eqv, r);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static name * g_prefix = nullptr;
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_sets add_core(type_checker & tc, simp_rule_sets const & s,
|
2015-06-02 00:53:25 +00:00
|
|
|
name const & id, levels const & univ_metas, expr const & e, expr const & h) {
|
2015-06-01 22:15:37 +00:00
|
|
|
list<expr_pair> ceqvs = to_ceqvs(tc, e, h);
|
|
|
|
environment const & env = tc.env();
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_sets new_s = s;
|
2015-06-01 22:15:37 +00:00
|
|
|
for (expr_pair const & p : ceqvs) {
|
|
|
|
expr new_e = p.first;
|
|
|
|
expr new_h = p.second;
|
|
|
|
bool is_perm = is_permutation_ceqv(env, new_e);
|
|
|
|
buffer<expr> metas;
|
|
|
|
unsigned idx = 0;
|
|
|
|
while (is_pi(new_e)) {
|
|
|
|
expr mvar = mk_metavar(name(*g_prefix, idx), binding_domain(new_e));
|
|
|
|
idx++;
|
|
|
|
metas.push_back(mvar);
|
|
|
|
new_e = instantiate(binding_body(new_e), mvar);
|
|
|
|
}
|
|
|
|
expr rel, lhs, rhs;
|
2015-07-22 22:46:00 +00:00
|
|
|
if (is_simp_relation(env, new_e, rel, lhs, rhs) && is_constant(rel)) {
|
2015-07-22 17:39:30 +00:00
|
|
|
new_s.insert(const_name(rel), simp_rule(id, univ_metas, to_list(metas), lhs, rhs, new_h, is_perm));
|
2015-06-01 22:15:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return new_s;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_sets add(type_checker & tc, simp_rule_sets const & s, name const & id, expr const & e, expr const & h) {
|
2015-06-02 00:53:25 +00:00
|
|
|
return add_core(tc, s, id, list<level>(), e, h);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_sets join(simp_rule_sets const & s1, simp_rule_sets const & s2) {
|
|
|
|
simp_rule_sets new_s1 = s1;
|
|
|
|
s2.for_each([&](name const & eqv, simp_rule const & r) {
|
2015-06-01 22:15:37 +00:00
|
|
|
new_s1.insert(eqv, r);
|
|
|
|
});
|
|
|
|
return new_s1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static name * g_class_name = nullptr;
|
|
|
|
static std::string * g_key = nullptr;
|
|
|
|
|
|
|
|
struct rrs_state {
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_sets m_sets;
|
2015-06-02 00:53:25 +00:00
|
|
|
name_set m_rnames;
|
2015-07-22 17:39:30 +00:00
|
|
|
name_map<simp_rule_sets> m_namespace_cache;
|
2015-06-01 22:15:37 +00:00
|
|
|
|
|
|
|
void add(environment const & env, name const & cname) {
|
|
|
|
type_checker tc(env);
|
|
|
|
declaration const & d = env.get(cname);
|
2015-06-02 00:53:25 +00:00
|
|
|
buffer<level> us;
|
|
|
|
unsigned num_univs = d.get_num_univ_params();
|
|
|
|
for (unsigned i = 0; i < num_univs; i++) {
|
|
|
|
us.push_back(mk_meta_univ(name(*g_prefix, i)));
|
|
|
|
}
|
|
|
|
levels ls = to_list(us);
|
|
|
|
expr e = instantiate_type_univ_params(d, ls);
|
|
|
|
expr h = mk_constant(cname, ls);
|
|
|
|
m_sets = add_core(tc, m_sets, cname, ls, e, h);
|
|
|
|
m_rnames.insert(cname);
|
|
|
|
m_namespace_cache.erase(get_namespace(env));
|
2015-06-01 22:15:37 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rrs_config {
|
|
|
|
typedef name entry;
|
|
|
|
typedef rrs_state state;
|
|
|
|
static void add_entry(environment const & env, io_state const &, state & s, entry const & e) {
|
|
|
|
s.add(env, e);
|
|
|
|
}
|
|
|
|
static name const & get_class_name() {
|
|
|
|
return *g_class_name;
|
|
|
|
}
|
|
|
|
static std::string const & get_serialization_key() {
|
|
|
|
return *g_key;
|
|
|
|
}
|
|
|
|
static void write_entry(serializer & s, entry const & e) {
|
|
|
|
s << e;
|
|
|
|
}
|
|
|
|
static entry read_entry(deserializer & d) {
|
|
|
|
entry e; d >> e; return e;
|
|
|
|
}
|
|
|
|
static optional<unsigned> get_fingerprint(entry const & e) {
|
|
|
|
return some(e.hash());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template class scoped_ext<rrs_config>;
|
|
|
|
typedef scoped_ext<rrs_config> rrs_ext;
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
environment add_simp_rule(environment const & env, name const & n, bool persistent) {
|
2015-06-01 22:15:37 +00:00
|
|
|
return rrs_ext::add_entry(env, get_dummy_ios(), n, persistent);
|
|
|
|
}
|
|
|
|
|
2015-07-23 00:21:47 +00:00
|
|
|
environment add_congr_rule(environment const & env, name const & n, bool persistent) {
|
|
|
|
// TODO(Leo):
|
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
bool is_simp_rule(environment const & env, name const & n) {
|
2015-06-02 00:53:25 +00:00
|
|
|
return rrs_ext::get_state(env).m_rnames.contains(n);
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
simp_rule_sets get_simp_rule_sets(environment const & env) {
|
2015-06-01 22:15:37 +00:00
|
|
|
return rrs_ext::get_state(env).m_sets;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void initialize_simp_rule_set() {
|
2015-06-01 22:15:37 +00:00
|
|
|
g_prefix = new name(name::mk_internal_unique_name());
|
|
|
|
g_class_name = new name("rrs");
|
|
|
|
g_key = new std::string("rrs");
|
|
|
|
rrs_ext::initialize();
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:39:30 +00:00
|
|
|
void finalize_simp_rule_set() {
|
2015-06-01 22:15:37 +00:00
|
|
|
rrs_ext::finalize();
|
|
|
|
delete g_key;
|
|
|
|
delete g_class_name;
|
|
|
|
delete g_prefix;
|
|
|
|
}
|
|
|
|
}
|