feat(library/init/meta/interactive): unfold is now based on the simp framework

See issue #1694.

There is an orthogonal issue. `simp` (and consequently `unfold`) cannot be used to
reduce projections (e.g., `has_add.add`). This issue has been
previously raised by @Armael, but it was not addressed yet.
This commit is contained in:
Leonardo de Moura 2017-07-02 11:30:48 -07:00
parent bd9f54cfe7
commit 70b27fb2d3
14 changed files with 56 additions and 31 deletions

View file

@ -59,6 +59,12 @@ For more details, see discussion [here](https://github.com/leanprover/lean/pull/
* `dunfold_occs` was deleted, the new `conv` tactical should be used instead.
* `unfold` tactic is now implemented on top of the `simp` tactics. So, we can use it to unfold
declarations defined using well founded recursion. The `unfold1` variant does not unfold recursively,
and it is shorthand for `unfold f {single_pass := tt}`.
Remark: in v3.2.0, `unfold` was just an alias for the `dunfold` tactic.
v3.2.0 (18 June 2017)
-------------

View file

@ -59,7 +59,7 @@ section semiring
variables [semiring α]
lemma one_add_one_eq_two : 1 + 1 = (2 : α) :=
begin unfold bit0, reflexivity end
by unfold bit0
theorem two_mul (n : α) : 2 * n = n + n :=
eq.trans (right_distrib 1 1 n) (by simp)

View file

@ -31,14 +31,14 @@ namespace int
by cases n; simp; refl
@[simp] lemma bodd_neg (n : ) : bodd (-n) = bodd n :=
by cases n; unfold has_neg.neg; simp [int.coe_nat_eq, int.neg, bodd]
by cases n; dunfold has_neg.neg; simp [int.coe_nat_eq, int.neg, bodd]
@[simp] lemma bodd_add (m n : ) : bodd (m + n) = bxor (bodd m) (bodd n) :=
by cases m with m m; cases n with n n; unfold has_add.add; simp [int.add, bodd];
by cases m with m m; cases n with n n; dunfold has_add.add; simp [int.add, bodd];
cases m.bodd; cases n.bodd; refl
@[simp] lemma bodd_mul (m n : ) : bodd (m * n) = bodd m && bodd n :=
by cases m with m m; cases n with n n; unfold has_mul.mul; simp [int.mul, bodd];
by cases m with m m; cases n with n n; dunfold has_mul.mul; simp [int.mul, bodd];
cases m.bodd; cases n.bodd; refl
theorem bodd_add_div2 : ∀ n, cond (bodd n) 1 0 + 2 * div2 n = n

View file

@ -16,13 +16,13 @@ meta def conv (α : Type u) :=
tactic α
meta instance : monad conv :=
by unfold conv; apply_instance
by dunfold conv; apply_instance
meta instance : monad_fail conv :=
by unfold conv; apply_instance
by dunfold conv; apply_instance
meta instance : alternative conv :=
by unfold conv; apply_instance
by dunfold conv; apply_instance
namespace conv
meta def convert (c : conv unit) (lhs : expr) (rel : name := `eq) : tactic (expr × expr) :=

View file

@ -233,11 +233,11 @@ meta def ith_arg_aux : expr → nat → expr
meta def ith_arg (e : expr) (i : nat) : expr :=
ith_arg_aux e (get_app_num_args e - i - 1)
meta def const_name : expr → name
meta def const_name : expr elab → name
| (const n ls) := n
| e := name.anonymous
meta def is_constant : expr → bool
meta def is_constant : expr elab → bool
| (const n ls) := tt
| e := ff

View file

@ -723,9 +723,9 @@ private meta def simp_hyps (cfg : simp_config) (discharger : tactic unit) : simp
| s [] := skip
| s (h::hs) := simp_hyp cfg discharger s h >> simp_hyps s hs
private meta def simp_core (cfg : simp_config) (discharger : tactic unit)
(no_dflt : bool) (ctx : list expr) (hs : list pexpr) (attr_names : list name) (ids : list name)
(locat : loc) : tactic unit :=
meta def simp_core (cfg : simp_config) (discharger : tactic unit)
(no_dflt : bool) (ctx : list expr) (hs : list pexpr) (attr_names : list name) (ids : list name)
(locat : loc) : tactic unit :=
do s ← mk_simp_set no_dflt attr_names hs ids,
s ← s.append ctx,
match locat : _ → tactic unit with
@ -899,10 +899,6 @@ match l with
intron n
end
/- TODO(Leo): add support for non-refl lemmas -/
meta def unfold (cs : parse ident*) (l : parse location) (cfg : dunfold_config := {}) : tactic unit :=
dunfold cs l cfg
private meta def delta_hyps : list name → list name → tactic unit
| cs [] := skip
| cs (h::hs) := get_local h >>= delta_at cs >> delta_hyps cs hs
@ -928,6 +924,34 @@ meta def unfold_projections : parse location → tactic unit
| (loc.ns hs) := unfold_projections_hyps hs
| (loc.wildcard) := do ls ← local_context, unfold_projections_hyps (ls.map expr.local_pp_name)
end interactive
meta def ids_to_pexprs (tac_name : name) (cs : list name) : tactic (list pexpr) :=
cs.mmap $ λ c, do
n ← resolve_name c,
hs ← get_eqn_lemmas_for ff n.const_name,
env ← get_env,
let p := env.is_projection n.const_name,
when (hs.empty ∧ p.is_none) (fail (sformat! "{tac_name} tactic failed, {c} does not have equational lemmas nor is a projection")),
return (expr.const c [])
structure unfold_config extends simp_config :=
(zeta := ff)
(proj := ff)
(eta := ff)
(canonize_instances := ff)
namespace interactive
open interactive interactive.types expr
meta def unfold (cs : parse ident*) (locat : parse location) (cfg : unfold_config := {}) : tactic unit :=
do es ← ids_to_pexprs "unfold" cs,
let no_dflt := tt,
simp_core cfg.to_simp_config failed no_dflt [] es [] [] locat
meta def unfold1 (cs : parse ident*) (locat : parse location) (cfg : unfold_config := {single_pass := tt}) : tactic unit :=
unfold cs locat cfg
meta def apply_opt_param : tactic unit :=
tactic.apply_opt_param

View file

@ -4,6 +4,6 @@ def some_lets :
def some_unfolded_lets (n : ) : ∃ v : , v = some_lets 5 n :=
begin
unfold some_lets,
dunfold some_lets,
-- admit
end

View file

@ -4,7 +4,7 @@ def some_lets :
def some_unfolded_lets (n : ) : Σ' v : , v = some_lets 5 n :=
begin
econstructor; unfold some_lets; econstructor
econstructor; dunfold some_lets; econstructor
end
meta def foo : tactic unit :=
@ -12,7 +12,7 @@ meta def foo : tactic unit :=
tactic.to_expr (``(1)) >>= tactic.unify g
def some_lifted_lets (n : ) : Σ' (v : ), v = psigma.fst (some_unfolded_lets n) :=
begin
econstructor; unfold some_unfolded_lets psigma.fst; symmetry; transitivity; symmetry;
econstructor; dunfold some_unfolded_lets psigma.fst; symmetry; transitivity; symmetry;
{
foo -- unify_reify_rhs_to_let_in
}

View file

@ -60,8 +60,7 @@ do 0 ::= 1,
lemma size_write (b : buffer nat) (i : nat) (h : i < b.size) (v : nat) : (b.write ⟨i, h⟩ v).size = b.size :=
begin
cases b,
unfold buffer.write buffer.size,
simp
unfold buffer.write buffer.size
end
open nat
@ -75,7 +74,7 @@ lemma init_mem_inv : ∀ n (b : buffer nat), n < b.size → (init_mem n).pre b
| (nat.succ n) b h :=
have n < b.size, from nat.lt_of_succ_lt h,
begin
unfold init_mem has_bind.and_then bind has_bind.bind hoare_state.bind, simp,
dunfold init_mem has_bind.and_then bind has_bind.bind hoare_state.bind, simp,
split,
{unfold hoare_state.assign, simp, exact h},
{intros _ _,

View file

@ -6,7 +6,7 @@ example (a b : nat) (p : nat → Prop) (h : p (g (nat.succ (nat.succ a)))) : p (
begin
unfold g at h,
do { h ← get_local `h >>= infer_type, t ← to_expr ```(p (nat.succ (nat.succ a) + 5)), guard (h = t) },
unfold has_add.add bit0 has_one.one nat.add,
dunfold has_add.add bit0 has_one.one nat.add,
unfold g,
do { t ← target, h ← get_local `h >>= infer_type, guard (t = h) },
assumption

View file

@ -63,7 +63,7 @@ lemma ex7 {α : Type u} (t : tree α) : t ≠ leaf → tree.size t > 0 :=
begin
induction t,
{intros, contradiction},
{intros, unfold size, apply nat.zero_lt_succ }
{intros, unfold tree.size, apply nat.zero_lt_succ }
end
inductive tree_list (α : Type u) : Type u

View file

@ -14,9 +14,7 @@ def g (a : nat) := a + 1
example : g 0 = 1 :=
begin
unfold g,
(target >>= check_expr ``(0 + 1 = 1)),
reflexivity
unfold g
end
example : f (f 0) = 2 :=

View file

@ -44,7 +44,7 @@ definition semigroup_morphism_product
begin
-- cf https://groups.google.com/d/msg/lean-user/bVs5FdjClp4/tfHiVjLIBAAJ
intros,
unfold has_mul.mul,
dunfold has_mul.mul,
dsimp,
simp
end

View file

@ -7,7 +7,5 @@ do e ← tactic.to_expr p, guard (t = e)
example (n : nat): f (n+1) n = n + 1 :=
begin
unfold f,
(tactic.target >>= check_expr ```((n + 1 = n + 1))),
reflexivity,
unfold f
end