feat(library/simplifier): add support for metavariables in conditional rewrite rules

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-01-29 08:34:04 -08:00
parent f101554e93
commit 92ba4e8b2d
7 changed files with 24 additions and 14 deletions

View file

@ -22,8 +22,9 @@ bool is_ceq(ro_environment const & env, expr e);
\brief Auxiliary functional object for creating "conditional equations" \brief Auxiliary functional object for creating "conditional equations"
*/ */
class to_ceqs_fn { class to_ceqs_fn {
ro_environment const & m_env; ro_environment const & m_env;
unsigned m_idx; optional<ro_metavar_env> const & m_menv;
unsigned m_idx;
static list<expr_pair> mk_singleton(expr const & e, expr const & H) { static list<expr_pair> mk_singleton(expr const & e, expr const & H) {
return list<expr_pair>(mk_pair(e, H)); return list<expr_pair>(mk_pair(e, H));
@ -33,6 +34,10 @@ class to_ceqs_fn {
return m_env->imported("if_then_else"); return m_env->imported("if_then_else");
} }
expr lift_free_vars(expr const & e, unsigned d) {
return ::lean::lift_free_vars(e, d, m_menv);
}
name mk_aux_name() { name mk_aux_name() {
if (m_idx == 0) { if (m_idx == 0) {
m_idx = 1; m_idx = 1;
@ -114,15 +119,15 @@ class to_ceqs_fn {
} }
} }
public: public:
to_ceqs_fn(ro_environment const & env):m_env(env), m_idx(0) {} to_ceqs_fn(ro_environment const & env, optional<ro_metavar_env> const & menv):m_env(env), m_menv(menv), m_idx(0) {}
list<expr_pair> operator()(expr const & e, expr const & H) { list<expr_pair> operator()(expr const & e, expr const & H) {
return filter(apply(e, H), [&](expr_pair const & p) { return is_ceq(m_env, p.first); }); return filter(apply(e, H), [&](expr_pair const & p) { return is_ceq(m_env, p.first); });
} }
}; };
list<expr_pair> to_ceqs(ro_environment const & env, expr const & e, expr const & H) { list<expr_pair> to_ceqs(ro_environment const & env, optional<ro_metavar_env> const & menv, expr const & e, expr const & H) {
return to_ceqs_fn(env)(e, H); return to_ceqs_fn(env, menv)(e, H);
} }
bool is_ceq(ro_environment const & env, expr e) { bool is_ceq(ro_environment const & env, expr e) {
@ -230,7 +235,10 @@ bool is_permutation_ceq(expr e) {
static int to_ceqs(lua_State * L) { static int to_ceqs(lua_State * L) {
ro_shared_environment env(L, 1); ro_shared_environment env(L, 1);
auto r = to_ceqs(env, to_expr(L, 2), to_expr(L, 3)); optional<ro_metavar_env> menv;
if (!lua_isnil(L, 2))
menv = to_metavar_env(L, 2);
auto r = to_ceqs(env, menv, to_expr(L, 3), to_expr(L, 4));
lua_newtable(L); lua_newtable(L);
int i = 1; int i = 1;
for (auto p : r) { for (auto p : r) {

View file

@ -7,6 +7,7 @@ Author: Leonardo de Moura
#pragma once #pragma once
#include "util/lua.h" #include "util/lua.h"
#include "kernel/environment.h" #include "kernel/environment.h"
#include "kernel/metavar.h"
#include "library/expr_pair.h" #include "library/expr_pair.h"
namespace lean { namespace lean {
/** /**
@ -26,7 +27,7 @@ namespace lean {
\remark if the left-hand-side of an equation does not contain all variables, then it is \remark if the left-hand-side of an equation does not contain all variables, then it is
discarded. That is, all elements in the resultant list satisfy the predicate \c is_ceq. discarded. That is, all elements in the resultant list satisfy the predicate \c is_ceq.
*/ */
list<expr_pair> to_ceqs(ro_environment const & env, expr const & e, expr const & H); list<expr_pair> to_ceqs(ro_environment const & env, optional<ro_metavar_env> const & menv, expr const & e, expr const & H);
/** /**
\brief Return true iff \c e is a conditional equation. \brief Return true iff \c e is a conditional equation.

View file

@ -25,9 +25,9 @@ rewrite_rule_set::rewrite_rule_set(rewrite_rule_set const & other):
m_env(other.m_env), m_rule_set(other.m_rule_set), m_disabled_rules(other.m_disabled_rules), m_congr_thms(other.m_congr_thms) {} m_env(other.m_env), m_rule_set(other.m_rule_set), m_disabled_rules(other.m_disabled_rules), m_congr_thms(other.m_congr_thms) {}
rewrite_rule_set::~rewrite_rule_set() {} rewrite_rule_set::~rewrite_rule_set() {}
void rewrite_rule_set::insert(name const & id, expr const & th, expr const & proof) { void rewrite_rule_set::insert(name const & id, expr const & th, expr const & proof, optional<ro_metavar_env> const & menv) {
ro_environment env(m_env); ro_environment env(m_env);
for (auto const & p : to_ceqs(env, th, proof)) { for (auto const & p : to_ceqs(env, menv, th, proof)) {
expr const & ceq = p.first; expr const & ceq = p.first;
expr const & proof = p.second; expr const & proof = p.second;
bool is_perm = is_permutation_ceq(ceq); bool is_perm = is_permutation_ceq(ceq);
@ -48,7 +48,7 @@ void rewrite_rule_set::insert(name const & th_name) {
ro_environment env(m_env); ro_environment env(m_env);
auto obj = env->find_object(th_name); auto obj = env->find_object(th_name);
if (obj && (obj->is_theorem() || obj->is_axiom())) { if (obj && (obj->is_theorem() || obj->is_axiom())) {
insert(th_name, obj->get_type(), mk_constant(th_name)); insert(th_name, obj->get_type(), mk_constant(th_name), none_ro_menv());
} else { } else {
throw exception(sstream() << "'" << th_name << "' is not a theorem nor an axiom"); throw exception(sstream() << "'" << th_name << "' is not a theorem nor an axiom");
} }

View file

@ -12,6 +12,7 @@ Author: Leonardo de Moura
#include "util/splay_tree.h" #include "util/splay_tree.h"
#include "util/name.h" #include "util/name.h"
#include "kernel/environment.h" #include "kernel/environment.h"
#include "kernel/metavar.h"
#include "kernel/formatter.h" #include "kernel/formatter.h"
#include "library/io_state_stream.h" #include "library/io_state_stream.h"
#include "library/simplifier/congr.h" #include "library/simplifier/congr.h"
@ -59,7 +60,7 @@ public:
\brief Convert the theorem \c th with proof \c proof into conditional rewrite rules, and \brief Convert the theorem \c th with proof \c proof into conditional rewrite rules, and
insert the rules into this rule set. The new rules are tagged with the given \c id. insert the rules into this rule set. The new rules are tagged with the given \c id.
*/ */
void insert(name const & id, expr const & th, expr const & proof); void insert(name const & id, expr const & th, expr const & proof, optional<ro_metavar_env> const & menv);
/** /**
\brief Convert the theorem/axiom named \c th_name in the environment into conditional rewrite rules, \brief Convert the theorem/axiom named \c th_name in the environment into conditional rewrite rules,

View file

@ -184,7 +184,7 @@ class simplifier_cell::imp {
updt_rule_set(imp & fn, expr const & H): updt_rule_set(imp & fn, expr const & H):
m_fn(fn), m_old(m_fn.m_rule_sets[0]), m_reset_cache(m_fn.m_cache) { m_fn(fn), m_old(m_fn.m_rule_sets[0]), m_reset_cache(m_fn.m_cache) {
lean_assert(const_type(H)); lean_assert(const_type(H));
m_fn.m_rule_sets[0].insert(g_local, *const_type(H), H); m_fn.m_rule_sets[0].insert(g_local, *const_type(H), H, m_fn.m_menv.to_some_menv());
} }
~updt_rule_set() { ~updt_rule_set() {
m_fn.m_rule_sets[0] = m_old; m_fn.m_rule_sets[0] = m_old;

View file

@ -43,7 +43,7 @@ static optional<proof_state> simplify_tactic(ro_environment const & env, io_stat
for (auto const & p : g.get_hypotheses()) { for (auto const & p : g.get_hypotheses()) {
if (tc.is_proposition(p.second, context(), menv)) { if (tc.is_proposition(p.second, context(), menv)) {
expr H = mk_constant(p.first, p.second); expr H = mk_constant(p.first, p.second);
rs.insert(g_assumption, p.second, H); rs.insert(g_assumption, p.second, H, some_ro_menv(menv));
} }
} }
} }

View file

@ -11,7 +11,7 @@ end
function test_ceq(name, expected, is_perm) function test_ceq(name, expected, is_perm)
local obj = env:find_object(name) local obj = env:find_object(name)
local r = to_ceqs(env, obj:get_type(), Const(name)) local r = to_ceqs(env, nil, obj:get_type(), Const(name))
show_ceqs(r) show_ceqs(r)
assert(#r == expected) assert(#r == expected)
if is_perm ~= nil then if is_perm ~= nil then