feat(library/tools/mini_crush): add tracing messages, and more examples
This commit is contained in:
parent
0fb5a01f17
commit
a41aac0e6a
3 changed files with 192 additions and 8 deletions
|
|
@ -81,20 +81,42 @@ meta def collect_inductive_from_target : tactic (list expr) :=
|
|||
do S ← target >>= collect_inductive,
|
||||
return $ list.qsort (λ e₁ e₂, size e₁ < size e₂) $ S^.to_list
|
||||
|
||||
meta def collect_inductive_hyps : tactic (list expr) :=
|
||||
local_context >>= mfoldl (λ r h, mcond (is_inductive h) (return $ h::r) (return r)) []
|
||||
|
||||
/- Induction -/
|
||||
|
||||
meta def try_induction_aux (cont : tactic unit) : list expr → tactic unit
|
||||
meta def try_induction_aux (cont : expr → tactic unit) : list expr → tactic unit
|
||||
| [] := failed
|
||||
| (e::es) := (step (induction e); cont; now) <|> try_induction_aux es
|
||||
| (e::es) := (step (induction e); cont e; now) <|> try_induction_aux es
|
||||
|
||||
meta def try_induction (cont : tactic unit) : tactic unit :=
|
||||
focus1 $ collect_inductive_from_target >>= mfilter (λ e, return $ e^.is_local_constant) >>= try_induction_aux cont
|
||||
meta def try_induction (cont : expr → tactic unit) : tactic unit :=
|
||||
focus1 $ collect_inductive_hyps >>= try_induction_aux cont
|
||||
|
||||
meta def strategy_1 (cfg : simp_config := {}) : tactic unit :=
|
||||
meta def report_failure (s : name) (e : option expr := none) : tactic unit :=
|
||||
when_tracing `mini_crush $
|
||||
match e with
|
||||
| none := trace ("FAILED '" ++ to_string s ++ "' at")
|
||||
| some e := (do p ← pp e, trace (to_fmt "FAILED '" ++ to_fmt s ++ "' processing " ++ p ++ to_fmt " at")) <|> trace ("FAILED '" ++ to_string s ++ "' at")
|
||||
end
|
||||
>> trace_state >> trace "--------------" >> failed
|
||||
|
||||
meta def close_or_fail (s : name) (e : expr) : tactic unit :=
|
||||
now
|
||||
<|> triv <|> reflexivity reducible <|> contradiction
|
||||
<|> (rsimp >> now) <|> try_for 1000 reflexivity
|
||||
<|> report_failure s (some e)
|
||||
|
||||
meta def strategy_1 (cfg : simp_config := {}) (n : name := "strategy 1") : tactic unit :=
|
||||
do s ← simp_lemmas.mk_default >>= add_relevant_eqns,
|
||||
try_induction (simph_intros_using s cfg >> (now <|> triv <|> reflexivity reducible <|> contradiction <|> rsimp <|> try_for 1000 reflexivity))
|
||||
try_induction (λ e, simph_intros_using s cfg >> close_or_fail n e)
|
||||
|
||||
meta def strategy_2 (cfg : simp_config := {}) : tactic unit :=
|
||||
intros >> strategy_1 cfg "strategy 2"
|
||||
|
||||
end mini_crush
|
||||
|
||||
meta def mini_crush :=
|
||||
mini_crush.strategy_1
|
||||
<|>
|
||||
mini_crush.strategy_2
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import tools.mini_crush
|
||||
/- "Proving in the Large" chapter of CPDT -/
|
||||
|
||||
inductive exp : Type
|
||||
|
|
@ -19,8 +20,8 @@ def times (k : nat) : exp → exp
|
|||
|
||||
attribute [simp] exp_eval times mul_add
|
||||
|
||||
theorem eval_times (k e) : exp_eval (times k e) = k * exp_eval e :=
|
||||
by induction e; simph
|
||||
theorem eval_times : ∀ (k e), exp_eval (times k e) = k * exp_eval e :=
|
||||
by mini_crush
|
||||
|
||||
def reassoc : exp → exp
|
||||
| (Const n) := (Const n)
|
||||
|
|
|
|||
161
tests/lean/run/cpdt3.lean
Normal file
161
tests/lean/run/cpdt3.lean
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
import tools.mini_crush
|
||||
/-
|
||||
This corresponds to Chapter 2 of CPDT, Some Quick Examples
|
||||
-/
|
||||
open list
|
||||
|
||||
inductive binop : Type
|
||||
| Plus
|
||||
| Times
|
||||
|
||||
open binop
|
||||
|
||||
inductive exp : Type
|
||||
| Const : nat → exp
|
||||
| Binop : binop → exp → exp → exp
|
||||
|
||||
open exp
|
||||
|
||||
def binop_denote : binop → nat → nat → nat
|
||||
| Plus := add
|
||||
| Times := mul
|
||||
|
||||
def exp_denote : exp → nat
|
||||
| (Const n) := n
|
||||
| (Binop b e1 e2) := (binop_denote b) (exp_denote e1) (exp_denote e2)
|
||||
|
||||
inductive instr : Type
|
||||
| iConst : ℕ → instr
|
||||
| iBinop : binop → instr
|
||||
|
||||
open instr
|
||||
|
||||
@[reducible]
|
||||
def prog := list instr
|
||||
def stack := list nat
|
||||
|
||||
def instr_denote (i : instr) (s : stack) : option stack :=
|
||||
match i with
|
||||
| (iConst n) := some (n :: s)
|
||||
| (iBinop b) :=
|
||||
match s with
|
||||
| (arg1 :: arg2 :: s') := some ((binop_denote b) arg1 arg2 :: s')
|
||||
| _ := none
|
||||
end
|
||||
end
|
||||
|
||||
def prog_denote : prog → stack → option stack
|
||||
| nil s := some s
|
||||
| (i :: p') s :=
|
||||
match instr_denote i s with
|
||||
| none := none
|
||||
| (some s') := prog_denote p' s'
|
||||
end
|
||||
|
||||
def compile : exp → prog
|
||||
| (Const n) := iConst n :: nil
|
||||
| (Binop b e1 e2) := compile e2 ++ compile e1 ++ iBinop b :: nil
|
||||
|
||||
/- This example needs a few facts from the list library. -/
|
||||
|
||||
@[simp] theorem compile_correct' :
|
||||
∀ e p s, prog_denote (compile e ++ p) s = prog_denote p (exp_denote e :: s) :=
|
||||
by intro; mini_crush
|
||||
|
||||
@[simp] theorem compile_correct : ∀ e, prog_denote (compile e) nil = some (exp_denote e :: nil) :=
|
||||
by mini_crush
|
||||
|
||||
inductive type : Type
|
||||
| Nat
|
||||
| Bool
|
||||
|
||||
open type
|
||||
|
||||
inductive tbinop : type → type → type → Type
|
||||
| TPlus : tbinop Nat Nat Nat
|
||||
| TTimes : tbinop Nat Nat Nat
|
||||
| TEq : ∀ t, tbinop t t Bool
|
||||
| TLt : tbinop Nat Nat Bool
|
||||
|
||||
open tbinop
|
||||
|
||||
inductive texp : type → Type
|
||||
| TNConst : nat → texp Nat
|
||||
| TBConst : bool → texp Bool
|
||||
| TBinop : ∀ {t1 t2 t}, tbinop t1 t2 t → texp t1 → texp t2 → texp t
|
||||
|
||||
open texp
|
||||
|
||||
def type_denote : type → Type
|
||||
| Nat := nat
|
||||
| Bool := bool
|
||||
|
||||
/- To simulate CPDT we need the next three operations. -/
|
||||
|
||||
def beq_nat (m n : ℕ) : bool := if m = n then tt else ff
|
||||
def eqb (b₁ b₂ : bool) : bool := if b₁ = b₂ then tt else ff
|
||||
def leb (m n : ℕ) : bool := if m < n then tt else ff
|
||||
|
||||
def tbinop_denote : Π {arg1 arg2 res : type},
|
||||
tbinop arg1 arg2 res → type_denote arg1 → type_denote arg2 → type_denote res
|
||||
| ._ ._ ._ TPlus := (add : ℕ → ℕ → ℕ)
|
||||
| ._ ._ ._ TTimes := (mul : ℕ → ℕ → ℕ)
|
||||
| ._ ._ ._ (TEq Nat) := beq_nat
|
||||
| ._ ._ ._ (TEq Bool) := eqb
|
||||
| ._ ._ ._ TLt := leb
|
||||
|
||||
def texp_denote : Π {t : type}, texp t → type_denote t
|
||||
| ._ (TNConst n) := n
|
||||
| ._ (TBConst b) := b
|
||||
| ._ (@TBinop _ _ _ b e1 e2) := (tbinop_denote b) (texp_denote e1) (texp_denote e2)
|
||||
|
||||
@[reducible]
|
||||
def tstack := list type
|
||||
|
||||
inductive tinstr : tstack → tstack → Type
|
||||
| TiNConst : Π s, nat → tinstr s (Nat :: s)
|
||||
| TiBConst : Π s, bool → tinstr s (Bool :: s)
|
||||
| TiBinop : Π {arg1 arg2 res s}, tbinop arg1 arg2 res → tinstr (arg1 :: arg2 :: s) (res :: s)
|
||||
|
||||
open tinstr
|
||||
|
||||
inductive tprog : tstack → tstack → Type
|
||||
| TNil : Π {s}, tprog s s
|
||||
| TCons : Π {s1 s2 s3}, tinstr s1 s2 → tprog s2 s3 → tprog s1 s3
|
||||
|
||||
open tprog
|
||||
|
||||
def vstack : tstack → Type
|
||||
| nil := unit
|
||||
| (t :: ts') := type_denote t × vstack ts'
|
||||
|
||||
def tinstr_denote : Π {ts ts' : tstack}, tinstr ts ts' → vstack ts → vstack ts'
|
||||
| ._ ._ (TiNConst ts n) := λ s, (n, s)
|
||||
| ._ ._ (TiBConst ts b) := λ s, (b, s)
|
||||
| ._ ._ (@TiBinop arg1 arg2 res s b) := λ ⟨arg1, ⟨arg2, s'⟩⟩, ((tbinop_denote b) arg1 arg2, s')
|
||||
|
||||
def tprog_denote : Π {ts ts' : tstack}, tprog ts ts' → vstack ts → vstack ts'
|
||||
| ._ ._ (@TNil _) := λ s, s
|
||||
| ._ ._ (@TCons _ _ _ i p') := λ s, tprog_denote p' (tinstr_denote i s)
|
||||
|
||||
def tconcat : Π {ts ts' ts'' : tstack}, tprog ts ts' → tprog ts' ts'' → tprog ts ts''
|
||||
| ._ ._ ts'' (@TNil _) p' := p'
|
||||
| ._ ._ ts'' (@TCons _ _ _ i p1) p' := TCons i (tconcat p1 p')
|
||||
|
||||
def tcompile : Π {t : type}, texp t → Π ts : tstack, tprog ts (t :: ts)
|
||||
| ._ (TNConst n) ts := TCons (TiNConst _ n) TNil
|
||||
| ._ (TBConst b) ts := TCons (TiBConst _ b) TNil
|
||||
| ._ (@TBinop _ _ _ b e1 e2) ts := tconcat (tcompile e2 _)
|
||||
(tconcat (tcompile e1 _) (TCons (TiBinop b) TNil))
|
||||
|
||||
@[simp] lemma tconcat_correct : ∀ ts ts' ts'' (p : tprog ts ts') (p' : tprog ts' ts'') (s : vstack ts),
|
||||
tprog_denote (tconcat p p') s = tprog_denote p' (tprog_denote p s) :=
|
||||
by mini_crush
|
||||
|
||||
@[simp] lemma tcompile_correct' : ∀ t (e : texp t) ts (s : vstack ts),
|
||||
tprog_denote (tcompile e ts) s = (texp_denote e, s) :=
|
||||
by intros t e; mini_crush
|
||||
|
||||
theorem tcompile_correct :
|
||||
∀ t (e : texp t), tprog_denote (tcompile e nil) () = (texp_denote e, ()) :=
|
||||
by mini_crush
|
||||
Loading…
Add table
Reference in a new issue