feat(library/init/meta/interactive): simp without foo ==> simp [-foo]
This commit also adds "exception" validation. A bad "exception" was being silently ignored. We can also exclude hypotheses. Example: `simp [*, -h]`
This commit is contained in:
parent
76799db032
commit
e24f3341d4
12 changed files with 143 additions and 58 deletions
|
|
@ -77,6 +77,10 @@ For more details, see discussion [here](https://github.com/leanprover/lean/pull/
|
|||
|
||||
* Deleted `simph` and `simp_using_hs` tactics. We should use `simp [*]` instead.
|
||||
|
||||
* Use `simp [-h]` and `dsimp [-h]` instead of `simp without h` and `dsimp without h`.
|
||||
Moreover, `simp [*, -h]` if `h` is a hypothesis, we are adding all hypotheses but `h`
|
||||
as additional simplification lemmas.
|
||||
|
||||
*API name changes*
|
||||
|
||||
* `tactic.dsimp` and `tactic.dsimp_core` => `tactic.dsimp_target`
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ section
|
|||
have array.read bkts' bidx = f L, from
|
||||
show ite (bidx = bidx) _ _ = _, by rw if_pos rfl,
|
||||
begin
|
||||
simp[array.iterate_aux] without add_comm,
|
||||
simp[array.iterate_aux, -add_comm],
|
||||
rw -(show bidx = ⟨bidx.1, h⟩, from fin.eq_of_veq rfl),
|
||||
refine ⟨array.iterate_aux bkts (λ_ bkt r, r ++ bkt) bidx.1 (le_of_lt h) [] ++ u, w, _⟩,
|
||||
rw -valid.modify_aux1 _ _ (le_refl _),
|
||||
|
|
@ -312,7 +312,7 @@ section
|
|||
have array.read bkts' bidx = f L, from
|
||||
show ite (bidx = bidx) _ _ = _, by rw if_pos rfl,
|
||||
begin
|
||||
simp[array.iterate_aux] without add_comm,
|
||||
simp[array.iterate_aux, -add_comm],
|
||||
rw [-(show bidx = ⟨bidx.1, h⟩, from fin.eq_of_veq rfl),
|
||||
-valid.modify_aux1 _ _ (le_refl _),
|
||||
this, hfl, hl],
|
||||
|
|
@ -365,7 +365,7 @@ theorem valid.replace_aux (a : α) (b : β a) : Π (l : list (Σ a, β a)), a
|
|||
| [] Hc := false.elim Hc
|
||||
| (⟨a', b'⟩::t) Hc := begin
|
||||
simp at Hc,
|
||||
simp [replace_aux] without and.comm,
|
||||
simp [replace_aux, -and.comm],
|
||||
exact match (by apply_instance : decidable (a' = a)) with
|
||||
| is_true e := match a', b', e with ._, b', rfl := ⟨[], t, b', rfl, rfl, by simp⟩ end
|
||||
| is_false ne :=
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ by induction l; intros; contradiction
|
|||
|
||||
lemma length_remove_nth : ∀ (l : list α) (i : ℕ), i < length l → length (remove_nth l i) = length l - 1
|
||||
| [] _ h := rfl
|
||||
| (x::xs) 0 h := by simp [remove_nth] without add_comm
|
||||
| (x::xs) 0 h := by simp [remove_nth, -add_comm]
|
||||
| (x::xs) (i+1) h := have i < length xs, from lt_of_succ_lt_succ h,
|
||||
by dsimp [remove_nth]; rw [length_remove_nth xs i this, nat.sub_add_cancel (lt_of_le_of_lt (nat.zero_le _) this)]; refl
|
||||
|
||||
|
|
|
|||
|
|
@ -1163,7 +1163,7 @@ by rw [div_eq_sub_div H (nat.le_add_left _ _), nat.add_sub_cancel]
|
|||
by rw [add_comm, add_div_right x H]
|
||||
|
||||
@[simp] theorem mul_div_right (n : ℕ) {m : ℕ} (H : m > 0) : m * n / m = n :=
|
||||
by {induction n; simp [*, mul_succ] without mul_comm}
|
||||
by {induction n; simp [*, mul_succ, -mul_comm]}
|
||||
|
||||
@[simp] theorem mul_div_left (m : ℕ) {n : ℕ} (H : n > 0) : m * n / n = m :=
|
||||
by rw [mul_comm, mul_div_right _ H]
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ meta def whnf : conv unit :=
|
|||
conv.whnf
|
||||
|
||||
meta def dsimp (no_dflt : parse only_flag) (es : parse tactic.simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(ids : parse without_ident_list) (cfg : tactic.dsimp_config := {}) : conv unit :=
|
||||
do (s, u) ← tactic.mk_simp_set no_dflt attr_names es ids,
|
||||
(cfg : tactic.dsimp_config := {}) : conv unit :=
|
||||
do (s, u) ← tactic.mk_simp_set no_dflt attr_names es,
|
||||
conv.dsimp (some s) u cfg
|
||||
|
||||
meta def trace_lhs : conv unit :=
|
||||
|
|
@ -109,9 +109,9 @@ do (r, lhs, _) ← tactic.target_lhs_rhs,
|
|||
update_lhs new_lhs pr
|
||||
|
||||
meta def simp (no_dflt : parse only_flag) (hs : parse tactic.simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(ids : parse without_ident_list) (cfg : tactic.simp_config_ext := {})
|
||||
(cfg : tactic.simp_config_ext := {})
|
||||
: conv unit :=
|
||||
do (s, u) ← tactic.mk_simp_set no_dflt attr_names hs ids,
|
||||
do (s, u) ← tactic.mk_simp_set no_dflt attr_names hs,
|
||||
(r, lhs, rhs) ← tactic.target_lhs_rhs,
|
||||
(new_lhs, pr) ← tactic.simplify s u lhs cfg.to_simp_config r cfg.discharger,
|
||||
update_lhs new_lhs pr,
|
||||
|
|
|
|||
|
|
@ -661,27 +661,46 @@ open expr interactive.types
|
|||
|
||||
meta inductive simp_arg_type : Type
|
||||
| all_hyps : simp_arg_type
|
||||
| except : name → simp_arg_type
|
||||
| expr : pexpr → simp_arg_type
|
||||
|
||||
|
||||
meta instance : has_reflect simp_arg_type
|
||||
| simp_arg_type.all_hyps := `(_)
|
||||
| (simp_arg_type.expr _) := `(_)
|
||||
| simp_arg_type.all_hyps := `(_)
|
||||
| (simp_arg_type.except _) := `(_)
|
||||
| (simp_arg_type.expr _) := `(_)
|
||||
|
||||
meta def simp_arg : parser simp_arg_type :=
|
||||
(tk "*" *> return simp_arg_type.all_hyps) <|> (simp_arg_type.expr <$> texpr)
|
||||
(tk "*" *> return simp_arg_type.all_hyps) <|> (tk "-" *> simp_arg_type.except <$> ident) <|> (simp_arg_type.expr <$> texpr)
|
||||
|
||||
meta def simp_arg_list : parser (list simp_arg_type) :=
|
||||
list_of simp_arg <|> return []
|
||||
|
||||
meta def decode_simp_arg_list (hs : list simp_arg_type) : list pexpr × bool :=
|
||||
let r : list pexpr × bool := hs.foldl
|
||||
(λ ⟨es, all⟩ h,
|
||||
match h with
|
||||
| simp_arg_type.all_hyps := (es, tt)
|
||||
| simp_arg_type.expr e := (e::es, all)
|
||||
end)
|
||||
([], ff) in
|
||||
(r.1.reverse, r.2)
|
||||
private meta def resolve_exception_ids (all_hyps : bool) : list name → list name → list name → tactic (list name × list name)
|
||||
| [] gex hex := return (gex.reverse, hex.reverse)
|
||||
| (id::ids) gex hex := do
|
||||
p ← resolve_name id,
|
||||
let e := p.erase_annotations.get_app_fn.erase_annotations,
|
||||
match e with
|
||||
| const n _ := resolve_exception_ids ids (n::gex) hex
|
||||
| local_const n _ _ _ := when (not all_hyps) (fail $ sformat! "invalid local exception {id}, '*' was not used") >>
|
||||
resolve_exception_ids ids gex (n::hex)
|
||||
| _ := fail $ sformat! "invalid exception {id}, unknown identifier"
|
||||
end
|
||||
|
||||
/- Return (hs, gex, hex, all) -/
|
||||
meta def decode_simp_arg_list (hs : list simp_arg_type) : tactic $ list pexpr × list name × list name × bool :=
|
||||
do
|
||||
let (hs, ex, all) := hs.foldl
|
||||
(λ r h,
|
||||
match r, h with
|
||||
| (es, ex, all), simp_arg_type.all_hyps := (es, ex, tt)
|
||||
| (es, ex, all), simp_arg_type.except id := (es, id::ex, all)
|
||||
| (es, ex, all), simp_arg_type.expr e := (e::es, ex, all)
|
||||
end)
|
||||
([], [], ff),
|
||||
(gex, hex) ← resolve_exception_ids all ex [] [],
|
||||
return (hs.reverse, gex, hex, all)
|
||||
|
||||
private meta def add_simps : simp_lemmas → list name → tactic simp_lemmas
|
||||
| s [] := return s
|
||||
|
|
@ -721,14 +740,18 @@ private meta def simp_lemmas.append_pexprs : simp_lemmas → list name → list
|
|||
| s u [] := return (s, u)
|
||||
| s u (l::ls) := do (s, u) ← simp_lemmas.add_pexpr s u l, simp_lemmas.append_pexprs s u ls
|
||||
|
||||
meta def mk_simp_set (no_dflt : bool) (attr_names : list name) (hs : list simp_arg_type) (ex : list name) : tactic (simp_lemmas × list name) :=
|
||||
do let (hs, add_hyps) := decode_simp_arg_list hs,
|
||||
meta def mk_simp_set (no_dflt : bool) (attr_names : list name) (hs : list simp_arg_type) : tactic (simp_lemmas × list name) :=
|
||||
do (hs, gex, hex, add_hyps) ← decode_simp_arg_list hs,
|
||||
s ← join_user_simp_lemmas no_dflt attr_names,
|
||||
(s, u) ← simp_lemmas.append_pexprs s [] hs,
|
||||
s ← if add_hyps then collect_ctx_simps >>= s.append else return s,
|
||||
s ← if add_hyps then do
|
||||
ctx ← collect_ctx_simps,
|
||||
let ctx := ctx.filter (λ h, h.local_uniq_name ∉ hex), -- remove local exceptions
|
||||
s.append ctx
|
||||
else return s,
|
||||
-- add equational lemmas, if any
|
||||
ex ← ex.mfor (λ n, list.cons n <$> get_eqn_lemmas_for tt n),
|
||||
return (simp_lemmas.erase s $ ex.join, u)
|
||||
gex ← gex.mfor (λ n, list.cons n <$> get_eqn_lemmas_for tt n),
|
||||
return (simp_lemmas.erase s $ gex.join, u)
|
||||
|
||||
end mk_simp_set
|
||||
|
||||
|
|
@ -740,9 +763,9 @@ private meta def simp_hyps (cfg : simp_config) (discharger : tactic unit) (s : s
|
|||
| (h::hs) := do h ← get_local h, simp_hyp s u h cfg discharger, simp_hyps hs
|
||||
|
||||
meta def simp_core (cfg : simp_config) (discharger : tactic unit)
|
||||
(no_dflt : bool) (hs : list simp_arg_type) (attr_names : list name) (ids : list name)
|
||||
(no_dflt : bool) (hs : list simp_arg_type) (attr_names : list name)
|
||||
(locat : loc) : tactic unit :=
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names hs ids,
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names hs,
|
||||
match locat : _ → tactic unit with
|
||||
| loc.wildcard :=
|
||||
do hs ← non_dep_prop_hyps,
|
||||
|
|
@ -772,9 +795,11 @@ It has many variants.
|
|||
The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.
|
||||
This is a convenient way to "unfold" `f`.
|
||||
|
||||
- `simp [*]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and all hypotheses.
|
||||
|
||||
- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas
|
||||
|
||||
- `simp without id_1 ... id_n` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,
|
||||
- `simp [-id_1, ... -id_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,
|
||||
but removes the ones named `id_i`s.
|
||||
|
||||
- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.
|
||||
|
|
@ -784,20 +809,23 @@ It has many variants.
|
|||
- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.
|
||||
-/
|
||||
meta def simp (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(ids : parse without_ident_list) (locat : parse location)
|
||||
(cfg : simp_config_ext := {}) : tactic unit :=
|
||||
simp_core cfg.to_simp_config cfg.discharger no_dflt hs attr_names ids locat
|
||||
(locat : parse location) (cfg : simp_config_ext := {}) : tactic unit :=
|
||||
simp_core cfg.to_simp_config cfg.discharger no_dflt hs attr_names locat
|
||||
|
||||
/-- Just construct the simp set and trace it -/
|
||||
meta def trace_simp_set (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list) : tactic unit :=
|
||||
do (s, _) ← mk_simp_set no_dflt attr_names hs,
|
||||
s.pp >>= trace
|
||||
|
||||
/-- Simplify the whole context, and use simplified hypotheses to simplify other hypotheses. -/
|
||||
meta def simp_all (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(ids : parse without_ident_list) (cfg : simp_config_ext := {}) : tactic unit :=
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names hs ids,
|
||||
meta def simp_all (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list) (cfg : simp_config_ext := {}) : tactic unit :=
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names hs,
|
||||
tactic.simp_all s u cfg.to_simp_config cfg.discharger,
|
||||
try tactic.triv, try (tactic.reflexivity reducible)
|
||||
|
||||
meta def simp_intros (ids : parse ident_*) (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(wo_ids : parse without_ident_list) (cfg : simp_intros_config := {}) : tactic unit :=
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names hs wo_ids,
|
||||
(cfg : simp_intros_config := {}) : tactic unit :=
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names hs,
|
||||
when (¬u.empty) (fail (sformat! "simp_intros tactic does not support {u}")),
|
||||
tactic.simp_intros s u ids cfg,
|
||||
try triv >> try (reflexivity reducible)
|
||||
|
|
@ -808,16 +836,13 @@ hs.mfor' (λ h_name, do h ← get_local h_name, dsimp_hyp h s u cfg)
|
|||
private meta def to_simp_arg_list (es : list pexpr) : list simp_arg_type :=
|
||||
es.map simp_arg_type.expr
|
||||
|
||||
meta def dsimp (no_dflt : parse only_flag) (es : parse opt_qexpr_list) (attr_names : parse with_ident_list)
|
||||
(ids : parse without_ident_list) (l : parse location) (cfg : dsimp_config := {}) : tactic unit :=
|
||||
meta def dsimp (no_dflt : parse only_flag) (es : parse simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(l : parse location) (cfg : dsimp_config := {}) : tactic unit :=
|
||||
do (s, u) ← mk_simp_set no_dflt attr_names es,
|
||||
match l with
|
||||
| (loc.ns []) := do (s, u) ← mk_simp_set no_dflt attr_names (to_simp_arg_list es) ids, dsimp_target s u cfg
|
||||
| (loc.ns hs) := do (s, u) ← mk_simp_set no_dflt attr_names (to_simp_arg_list es) ids, dsimp_hyps s u hs cfg
|
||||
| (loc.wildcard) := do ls ← local_context,
|
||||
n ← revert_lst ls,
|
||||
(s, u) ← mk_simp_set no_dflt attr_names (to_simp_arg_list es) ids,
|
||||
dsimp_target s u cfg,
|
||||
intron n
|
||||
| (loc.ns []) := dsimp_target s u cfg
|
||||
| (loc.ns hs) := dsimp_hyps s u hs cfg
|
||||
| (loc.wildcard) := do ls ← local_context, n ← revert_lst ls, dsimp_target s u cfg, intron n
|
||||
end
|
||||
|
||||
/--
|
||||
|
|
@ -942,7 +967,7 @@ open interactive interactive.types expr
|
|||
meta def unfold (cs : parse ident*) (locat : parse location) (cfg : unfold_config := {}) : tactic unit :=
|
||||
do es ← ids_to_simp_arg_list "unfold" cs,
|
||||
let no_dflt := tt,
|
||||
simp_core cfg.to_simp_config failed no_dflt es [] [] locat
|
||||
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
|
||||
|
|
|
|||
|
|
@ -252,12 +252,12 @@ slift (tactic.interactive.induction p rec_name ids revert)
|
|||
open tactic
|
||||
|
||||
/-- Simplify the target type of the main goal. -/
|
||||
meta def simp (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list) (ids : parse without_ident_list)
|
||||
meta def simp (no_dflt : parse only_flag) (hs : parse simp_arg_list) (attr_names : parse with_ident_list)
|
||||
(cfg : simp_config_ext := {}) : smt_tactic unit :=
|
||||
tactic.interactive.simp no_dflt hs attr_names ids (loc.ns []) cfg
|
||||
tactic.interactive.simp no_dflt hs attr_names (loc.ns []) cfg
|
||||
|
||||
meta def dsimp (no_dflt : parse only_flag) (es : parse opt_qexpr_list) (attr_names : parse with_ident_list) (ids : parse without_ident_list) : smt_tactic unit :=
|
||||
tactic.interactive.dsimp no_dflt es attr_names ids (loc.ns [])
|
||||
meta def dsimp (no_dflt : parse only_flag) (es : parse simp_arg_list) (attr_names : parse with_ident_list) : smt_tactic unit :=
|
||||
tactic.interactive.dsimp no_dflt es attr_names (loc.ns [])
|
||||
|
||||
meta def rsimp : smt_tactic unit :=
|
||||
do ccs ← to_cc_state, _root_.rsimp.rsimplify_goal ccs
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{"msgs":[{"caption":"","file_name":"f","pos_col":2,"pos_line":5,"severity":"error","text":"simplify tactic failed to simplify\nstate:\n⊢ false"}],"response":"all_messages"}
|
||||
{"message":"file invalidated","response":"ok","seq_num":0}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp without id_1 ... id_n` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"state":"⊢ false","tactic_params":["only?","[(* | expr), ...]?","(with id*)?","(without id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.without_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":6}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp without id_1 ... id_n` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"tactic_param_idx":0,"tactic_params":["only?","[(* | expr), ...]?","(with id*)?","(without id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.without_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":8}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp without id_1 ... id_n` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"tactic_param_idx":1,"tactic_params":["only?","[(* | expr), ...]?","(with id*)?","(without id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.without_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":10}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp without id_1 ... id_n` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"tactic_param_idx":2,"tactic_params":["only?","[(* | expr), ...]?","(with id*)?","(without id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.without_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":12}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp [*]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and all hypotheses.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp [-id_1, ... -id_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"state":"⊢ false","tactic_params":["only?","[(* | (- id | expr)), ...]?","(with id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":6}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp [*]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and all hypotheses.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp [-id_1, ... -id_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"tactic_param_idx":0,"tactic_params":["only?","[(* | (- id | expr)), ...]?","(with id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":8}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp [*]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and all hypotheses.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp [-id_1, ... -id_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"tactic_param_idx":1,"tactic_params":["only?","[(* | (- id | expr)), ...]?","(with id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":10}
|
||||
{"record":{"doc":"This tactic uses lemmas and hypotheses to simplify the main goal target or non-dependent hypotheses.\nIt has many variants.\n\n- `simp` simplifies the main goal target using lemmas tagged with the attribute `[simp]`.\n\n- `simp [h_1, ..., h_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and the given `h_i`s.\n The `h_i`'s are terms. If a `h_i` is a definition `f`, then the equational lemmas associated with `f` are used.\n This is a convenient way to \"unfold\" `f`.\n\n- `simp [*]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]` and all hypotheses.\n\n- `simp only [h_1, ..., h_n]` is like `simp [h_1, ..., h_n]` but does not use `[simp]` lemmas\n\n- `simp [-id_1, ... -id_n]` simplifies the main goal target using the lemmas tagged with the attribute `[simp]`,\n but removes the ones named `id_i`s.\n\n- `simp at h_1 ... h_n` simplifies the non dependent hypotheses `h_1 : T_1` ... `h_n : T : n`. The tactic fails if the target or another hypothesis depends on one of them.\n\n- `simp at *` simplifies all the hypotheses and the goal.\n\n- `simp with attr_1 ... attr_n` simplifies the main goal target using the lemmas tagged with any of the attributes `[attr_1]`, ..., `[attr_n]` or `[simp]`.","source":,"tactic_param_idx":2,"tactic_params":["only?","[(* | (- id | expr)), ...]?","(with id*)?","(at (* | id*))?","simp_config_ext?"],"text":"simp","type":"interactive.parse interactive.types.only_flag → interactive.parse simp_arg_list → interactive.parse interactive.types.with_ident_list → interactive.parse interactive.types.location → opt_param simp_config_ext {to_simp_config := {max_steps := simp.default_max_steps, contextual := ff, lift_eq := tt, canonize_instances := tt, canonize_proofs := ff, use_axioms := tt, zeta := tt, beta := tt, eta := tt, proj := tt, iota := tt, single_pass := ff, fail_if_unchanged := tt, memoize := tt}, discharger := failed unit} → tactic unit"},"response":"ok","seq_num":12}
|
||||
{"record":{"full-id":"tactic.get_env","source":,"tactic_params":[],"type":"tactic environment"},"response":"ok","seq_num":14}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ end
|
|||
|
||||
example (a b c : nat) : g (f 1, f 2) = 41 :=
|
||||
begin
|
||||
dsimp [f] without gax,
|
||||
dsimp [f, -gax],
|
||||
guard_target g (20 + 0, 20 + 1) = 41,
|
||||
dsimp [g],
|
||||
guard_target 20 + 0 + (20 + 1) = 41,
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ attribute [simp] boo bla
|
|||
example (a b : nat) : a = b → h 0 a = b :=
|
||||
begin
|
||||
intro h,
|
||||
simp [h] without bla -- should fail if bla is used
|
||||
simp [h, -bla] -- should fail if bla is used
|
||||
end
|
||||
open tactic
|
||||
example (a b : nat) : a = b → h 0 a = b :=
|
||||
by simp without bla {contextual := tt}
|
||||
by simp [-bla] {contextual := tt}
|
||||
|
|
|
|||
34
tests/lean/simp_except.lean
Normal file
34
tests/lean/simp_except.lean
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
constant f : nat → nat
|
||||
|
||||
namespace foo
|
||||
axiom fax : ∀ x, f x = x
|
||||
end foo
|
||||
|
||||
attribute [simp] foo.fax
|
||||
|
||||
example (a : nat) : f a = a :=
|
||||
by simp -- works
|
||||
|
||||
example (a : nat) : f a = a :=
|
||||
by simp [-fax] -- Error: unknown identifier 'fax'
|
||||
|
||||
example (a : nat) : f a = a :=
|
||||
by simp [-foo.fax] -- Error: simplify failed to simplify
|
||||
|
||||
section
|
||||
open foo
|
||||
example (a : nat) : f a = a :=
|
||||
by simp [-fax] -- Error: simplify failed to simplify
|
||||
end
|
||||
|
||||
example (a : nat) (h : a = 0) : a = 0 :=
|
||||
by simp [-h] -- Error: invalid local exception h, '*' was not used
|
||||
|
||||
example (a : nat) (h : a = 0) : a = 0 :=
|
||||
by simp [*, -h] -- Error: simplify failed to simplify
|
||||
|
||||
example (a : nat) (h : a = 0) : a = 0 :=
|
||||
by simp [*] -- works
|
||||
|
||||
example (a b : nat) (h : b = 0) (h₁ : a = b) (h₂ : b = a) : b = 0 :=
|
||||
by simp [*, -h₁, -h₂] -- we can prevent loops by removing "bad" hypotheses
|
||||
22
tests/lean/simp_except.lean.expected.out
Normal file
22
tests/lean/simp_except.lean.expected.out
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
simp_except.lean:13:3: error: unknown identifier 'fax'
|
||||
state:
|
||||
a : ℕ
|
||||
⊢ f a = a
|
||||
simp_except.lean:16:3: error: simplify tactic failed to simplify
|
||||
state:
|
||||
a : ℕ
|
||||
⊢ f a = a
|
||||
simp_except.lean:21:3: error: simplify tactic failed to simplify
|
||||
state:
|
||||
a : ℕ
|
||||
⊢ f a = a
|
||||
simp_except.lean:25:3: error: invalid local exception h, '*' was not used
|
||||
state:
|
||||
a : ℕ,
|
||||
h : a = 0
|
||||
⊢ a = 0
|
||||
simp_except.lean:28:3: error: simplify tactic failed to simplify
|
||||
state:
|
||||
a : ℕ,
|
||||
h : a = 0
|
||||
⊢ a = 0
|
||||
Loading…
Add table
Reference in a new issue