feat(library/tactic/inversion_tactic): add 'case ... with ...' variant that allows user to specify names for new hypotheses
This commit is contained in:
parent
22b2f3c78c
commit
e0debca771
4 changed files with 60 additions and 13 deletions
|
@ -57,8 +57,7 @@ opaque definition revert (e : expr) : tactic := builtin
|
||||||
opaque definition unfold (e : expr) : tactic := builtin
|
opaque definition unfold (e : expr) : tactic := builtin
|
||||||
opaque definition exact (e : expr) : tactic := builtin
|
opaque definition exact (e : expr) : tactic := builtin
|
||||||
opaque definition trace (s : string) : tactic := builtin
|
opaque definition trace (s : string) : tactic := builtin
|
||||||
opaque definition inversion (e : expr) : tactic := builtin
|
opaque definition inversion (id : expr) : tactic := builtin
|
||||||
definition cases := inversion
|
|
||||||
|
|
||||||
notation a `↦` b := rename a b
|
notation a `↦` b := rename a b
|
||||||
|
|
||||||
|
@ -66,17 +65,21 @@ inductive expr_list : Type :=
|
||||||
nil : expr_list,
|
nil : expr_list,
|
||||||
cons : expr → expr_list → expr_list
|
cons : expr → expr_list → expr_list
|
||||||
|
|
||||||
opaque definition intro_lst (es : expr_list) : tactic := builtin
|
opaque definition inversion_with (id : expr) (ids : expr_list) : tactic := builtin
|
||||||
|
notation `cases` a := inversion a
|
||||||
|
notation `cases` a `with` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := inversion_with a l
|
||||||
|
|
||||||
|
opaque definition intro_lst (ids : expr_list) : tactic := builtin
|
||||||
notation `intros` := intro_lst expr_list.nil
|
notation `intros` := intro_lst expr_list.nil
|
||||||
notation `intros` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := intro_lst l
|
notation `intros` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := intro_lst l
|
||||||
|
|
||||||
opaque definition generalize_lst (es : expr_list) : tactic := builtin
|
opaque definition generalize_lst (es : expr_list) : tactic := builtin
|
||||||
notation `generalizes` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := generalize_lst l
|
notation `generalizes` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := generalize_lst l
|
||||||
|
|
||||||
opaque definition clear_lst (es : expr_list) : tactic := builtin
|
opaque definition clear_lst (ids : expr_list) : tactic := builtin
|
||||||
notation `clears` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := clear_lst l
|
notation `clears` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := clear_lst l
|
||||||
|
|
||||||
opaque definition revert_lst (es : expr_list) : tactic := builtin
|
opaque definition revert_lst (ids : expr_list) : tactic := builtin
|
||||||
notation `reverts` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := revert_lst l
|
notation `reverts` `(` l:(foldr `,` (h t, expr_list.cons h t) expr_list.nil) `)` := revert_lst l
|
||||||
|
|
||||||
infixl `;`:15 := and_then
|
infixl `;`:15 := and_then
|
||||||
|
|
|
@ -18,6 +18,7 @@ class inversion_tac {
|
||||||
environment const & m_env;
|
environment const & m_env;
|
||||||
io_state const & m_ios;
|
io_state const & m_ios;
|
||||||
proof_state const & m_ps;
|
proof_state const & m_ps;
|
||||||
|
list<name> m_ids;
|
||||||
name_generator m_ngen;
|
name_generator m_ngen;
|
||||||
substitution m_subst;
|
substitution m_subst;
|
||||||
std::unique_ptr<type_checker> m_tc;
|
std::unique_ptr<type_checker> m_tc;
|
||||||
|
@ -192,7 +193,14 @@ class inversion_tac {
|
||||||
expr g_type = g.get_type();
|
expr g_type = g.get_type();
|
||||||
for (unsigned i = 0; i < nargs; i++) {
|
for (unsigned i = 0; i < nargs; i++) {
|
||||||
expr type = binding_domain(g_type);
|
expr type = binding_domain(g_type);
|
||||||
expr new_h = mk_local(m_ngen.next(), get_unused_name(binding_name(g_type), new_hyps), type, binder_info());
|
name new_h_name;
|
||||||
|
if (m_ids) {
|
||||||
|
new_h_name = head(m_ids);
|
||||||
|
m_ids = tail(m_ids);
|
||||||
|
} else {
|
||||||
|
new_h_name = binding_name(g_type);
|
||||||
|
}
|
||||||
|
expr new_h = mk_local(m_ngen.next(), get_unused_name(new_h_name, new_hyps), type, binder_info());
|
||||||
new_hyps.push_back(new_h);
|
new_hyps.push_back(new_h);
|
||||||
g_type = instantiate(binding_body(g_type), new_h);
|
g_type = instantiate(binding_body(g_type), new_h);
|
||||||
}
|
}
|
||||||
|
@ -400,8 +408,8 @@ class inversion_tac {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inversion_tac(environment const & env, io_state const & ios, proof_state const & ps):
|
inversion_tac(environment const & env, io_state const & ios, proof_state const & ps, list<name> const & ids):
|
||||||
m_env(env), m_ios(ios), m_ps(ps),
|
m_env(env), m_ios(ios), m_ps(ps), m_ids(ids),
|
||||||
m_ngen(m_ps.get_ngen()),
|
m_ngen(m_ps.get_ngen()),
|
||||||
m_tc(mk_type_checker(m_env, m_ngen.mk_child(), m_ps.relax_main_opaque())) {
|
m_tc(mk_type_checker(m_env, m_ngen.mk_child(), m_ps.relax_main_opaque())) {
|
||||||
}
|
}
|
||||||
|
@ -432,9 +440,9 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tactic inversion_tactic(name const & n) {
|
tactic inversion_tactic(name const & n, list<name> const & ids) {
|
||||||
auto fn = [=](environment const & env, io_state const & ios, proof_state const & ps) -> optional<proof_state> {
|
auto fn = [=](environment const & env, io_state const & ios, proof_state const & ps) -> optional<proof_state> {
|
||||||
inversion_tac tac(env, ios, ps);
|
inversion_tac tac(env, ios, ps, ids);
|
||||||
return tac.execute(n);
|
return tac.execute(n);
|
||||||
};
|
};
|
||||||
return tactic01(fn);
|
return tactic01(fn);
|
||||||
|
@ -443,8 +451,15 @@ tactic inversion_tactic(name const & n) {
|
||||||
void initialize_inversion_tactic() {
|
void initialize_inversion_tactic() {
|
||||||
register_tac(name({"tactic", "inversion"}),
|
register_tac(name({"tactic", "inversion"}),
|
||||||
[](type_checker &, elaborate_fn const &, expr const & e, pos_info_provider const *) {
|
[](type_checker &, elaborate_fn const &, expr const & e, pos_info_provider const *) {
|
||||||
name n = tactic_expr_to_id(app_arg(e), "invalid 'inversion' tactic, argument must be an identifier");
|
name n = tactic_expr_to_id(app_arg(e), "invalid 'inversion/cases' tactic, argument must be an identifier");
|
||||||
return inversion_tactic(n);
|
return inversion_tactic(n, list<name>());
|
||||||
|
});
|
||||||
|
register_tac(name({"tactic", "inversion_with"}),
|
||||||
|
[](type_checker &, elaborate_fn const &, expr const & e, pos_info_provider const *) {
|
||||||
|
name n = tactic_expr_to_id(app_arg(app_fn(e)), "invalid 'cases-with' tactic, argument must be an identifier");
|
||||||
|
buffer<name> ids;
|
||||||
|
get_tactic_id_list_elements(app_arg(e), ids, "invalid 'cases-with' tactic, list of identifiers expected");
|
||||||
|
return inversion_tactic(n, to_list(ids.begin(), ids.end()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
void finalize_inversion_tactic() {}
|
void finalize_inversion_tactic() {}
|
||||||
|
|
|
@ -8,7 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include "library/tactic/tactic.h"
|
#include "library/tactic/tactic.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
tactic inversion_tactic(name const & from, name const & to);
|
tactic inversion_tactic(name const & n, list<name> const & ids = list<name>());
|
||||||
void initialize_inversion_tactic();
|
void initialize_inversion_tactic();
|
||||||
void finalize_inversion_tactic();
|
void finalize_inversion_tactic();
|
||||||
}
|
}
|
||||||
|
|
29
tests/lean/run/vec_inv2.lean
Normal file
29
tests/lean/run/vec_inv2.lean
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import data.nat.basic data.empty data.prod
|
||||||
|
open nat eq.ops prod
|
||||||
|
|
||||||
|
inductive vector (T : Type) : ℕ → Type :=
|
||||||
|
nil {} : vector T 0,
|
||||||
|
cons : T → ∀{n}, vector T n → vector T (succ n)
|
||||||
|
|
||||||
|
set_option pp.metavar_args true
|
||||||
|
set_option pp.implicit true
|
||||||
|
set_option pp.notation false
|
||||||
|
|
||||||
|
namespace vector
|
||||||
|
variables {A B C : Type}
|
||||||
|
variables {n m : nat}
|
||||||
|
|
||||||
|
theorem z_cases_on {C : vector A 0 → Type} (v : vector A 0) (Hnil : C nil) : C v :=
|
||||||
|
begin
|
||||||
|
cases v,
|
||||||
|
apply Hnil
|
||||||
|
end
|
||||||
|
|
||||||
|
protected definition destruct (v : vector A (succ n)) {P : Π {n : nat}, vector A (succ n) → Type}
|
||||||
|
(H : Π {n : nat} (h : A) (t : vector A n), P (cons h t)) : P v :=
|
||||||
|
begin
|
||||||
|
cases v with (h', n', t'),
|
||||||
|
apply (H h' t')
|
||||||
|
end
|
||||||
|
|
||||||
|
end vector
|
Loading…
Reference in a new issue