Skip to content

Commit 49079cb

Browse files
Example of using match_expr instead of qq in Ltac
1 parent 6cae3a0 commit 49079cb

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

Katydid/Std/Balistic.lean

+6-6
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ local elab "list_empty_matcher" : tactic => newTactic do
2727
-- x :: xs ≠ []
2828
run `(tactic| apply list_cons_ne_nil )
2929
| _ =>
30-
let hyps ← getHypotheses
30+
let hyps ← getHypothesesProp
3131
for (name, ty) in hyps do
3232
let matched ← match ty with
3333
| ~q([] = $x :: $xs) =>
@@ -146,7 +146,7 @@ local elab "list_single_matcher" : tactic => newTactic do
146146
-- x :: xs = y :: ys -> x = y /\ xs = ys
147147
run `(tactic| apply list_cons_eq.mpr)
148148
| _ =>
149-
let hyps ← getHypotheses
149+
let hyps ← getHypothesesProp
150150
for (name, ty) in hyps do
151151
let matched ← match ty with
152152
| ~q($xs ++ $ys = [$a]) =>
@@ -281,7 +281,7 @@ example (xs ys zs: List α):
281281
list_app
282282

283283
local elab "wreck_exists" : tactic => newTactic do
284-
let hyps ← getHypotheses
284+
let hyps ← getHypothesesProp
285285
for (name, ty) in hyps do
286286
let matched ← match ty with
287287
| ~q(∃ x _y, $p x) =>
@@ -298,7 +298,7 @@ local elab "wreck_exists" : tactic => newTactic do
298298
throwError "tactic 'wreck_exists' did not match the goal or any hypotheses"
299299

300300
local elab "wreck_conj": tactic => newTactic do
301-
let hyps ← getHypotheses
301+
let hyps ← getHypothesesProp
302302
for (name, ty) in hyps do
303303
let matched ← match ty with
304304
| ~q($x /\ $y) =>
@@ -320,7 +320,7 @@ local elab "wreck_conj": tactic => newTactic do
320320
-- - ys = [] /\ zs = x :: xs
321321
-- - .
322322
local elab "list_app_uncons" : tactic => newTactic do
323-
let hyps ← getHypotheses
323+
let hyps ← getHypothesesProp
324324
for (name, ty) in hyps do
325325
let matched ← match ty with
326326
| ~q($ys ++ $zs = $x :: $xs ) =>
@@ -367,7 +367,7 @@ example (xs ys: List α) (x y: α):
367367

368368
-- garbage_collect_rfl removes hypotheses of the form x = x
369369
local elab "garbage_collect_rfl" : tactic => newTactic do
370-
let hyps ← getHypotheses
370+
let hyps ← getHypothesesProp
371371
for (name, ty) in hyps do
372372
let matched ← match ty with
373373
| ~q($x = $y) =>

Katydid/Std/Ltac.lean

+32-9
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ def newTactic (x : Lean.Elab.Tactic.TacticM α) : Lean.Elab.Tactic.TacticM α :=
1919
private def castToProp (e: Lean.Expr) : Lean.Elab.Tactic.TacticM (Option Q(Prop)) := do
2020
Qq.checkTypeQ (u := Lean.levelOne) e q(Prop)
2121

22-
-- getHypotheses returns the hypotheses as an array of tuples of (Hypothesis name, Q(Prop))
22+
-- getHypothesesProp returns the hypotheses as an array of tuples of (Hypothesis name, Q(Prop))
2323
-- This way the hypothesis Q(Prop) can be used in a pattern match and
2424
-- the name can be used to refer to the hypothesis in other tactics
25-
def getHypotheses : Lean.Elab.Tactic.TacticM (Array (Lean.Syntax.Ident × Q(Prop))) := do
25+
def getHypothesesProp : Lean.Elab.Tactic.TacticM (Array (Lean.Syntax.Ident × Q(Prop))) := do
2626
let mut res := #[]
2727
for localDecl in ← Lean.MonadLCtx.getLCtx do
2828
if let some typ ← castToProp localDecl.type then
@@ -32,7 +32,7 @@ def getHypotheses : Lean.Elab.Tactic.TacticM (Array (Lean.Syntax.Ident × Q(Prop
3232

3333
-- a tactic that prints the hypotheses and their types
3434
elab "print_hypotheses" : tactic => do
35-
let hyps ← getHypotheses
35+
let hyps ← getHypothesesProp
3636
for (name, ty) in hyps do
3737
Lean.logInfo m!"{name}: {ty}"
3838

@@ -41,14 +41,37 @@ example (_H1: 1 = 1) (_H2: 2 = 2): True := by
4141
simp
4242

4343
-- a tactic that prints the hypotheses, but only if they match a pattern
44-
local elab "example_print_rfl_hypotheses" : tactic => do
45-
let hyps ← getHypotheses
44+
local elab "example_print_rfl_hypotheses_prop" : tactic => do
45+
let hyps ← getHypothesesProp
4646
for (name, ty) in hyps do
4747
if let ~q($x = $y) := ty then
4848
if ← Lean.Meta.isExprDefEq x y then
4949
Lean.logInfo m!"{name} is rfl"
5050

5151
example (_H1 : x = 5) (_H2 : 2 = 2) (_H3: y = y) (H4: 5 = 4): False := by
52+
example_print_rfl_hypotheses_prop
53+
contradiction
54+
55+
def getHypotheses : Lean.Elab.Tactic.TacticM (Array (Lean.Syntax.Ident × Lean.Expr)) := do
56+
let mut res := #[]
57+
for localDecl in ← Lean.MonadLCtx.getLCtx do
58+
let name := Lean.mkIdent localDecl.userName
59+
res := res.push (name, localDecl.type)
60+
return res
61+
62+
-- use match_expr instead of Qq
63+
-- see examples in https://github.com/leanprover/lean4/blob/a5162ca7489bfdbf1a2851cffd8fdcca9d2b9b56/src/Lean/Elab/Tactic/Omega/Frontend.lean#L431
64+
local elab "example_print_rfl_hypotheses" : tactic => do
65+
let hyps ← getHypotheses
66+
for (name, ty) in hyps do
67+
match_expr ty with
68+
| Eq _ x y =>
69+
if ← Lean.Meta.isExprDefEq x y then
70+
Lean.logInfo m!"{name} is rfl"
71+
| _ =>
72+
continue
73+
74+
example (_G1 : x > 5) (_G2 : 2 = 2) (_G3: y = y) (G4: 5 = 4): False := by
5275
example_print_rfl_hypotheses
5376
contradiction
5477

@@ -59,7 +82,7 @@ def run (t: Lean.Elab.Tactic.TacticM (Lean.TSyntax `tactic)): Lean.Elab.Tactic.T
5982

6083
-- an example tactic that applies a hypothesis to the goal if it matches a pattern
6184
local elab "example_apply_hypothesis" : tactic => do
62-
let hyps ← getHypotheses
85+
let hyps ← getHypothesesProp
6386
for (name, ty) in hyps do
6487
if let ~q((((($a : Prop)) → $b) : Prop)) := ty then
6588
run `(tactic| apply $name )
@@ -78,7 +101,7 @@ def getGoalProp : Lean.Elab.Tactic.TacticM Q(Prop) := do
78101
-- An example to check whether the goal is already an hypothesis
79102
local elab "example_assumption_tactic" : tactic => do
80103
let goal ← getGoalProp
81-
let hyps ← getHypotheses
104+
let hyps ← getHypothesesProp
82105
for (name, ty) in hyps do
83106
if ← Lean.Meta.isExprDefEq ty goal then
84107
run `(tactic| exact $name )
@@ -129,7 +152,7 @@ def mkHyp (suggestion: String) (t: Lean.Elab.Tactic.TacticM (Lean.TSyntax `term)
129152
-- an example that tries to apply a bunch to tactics to specific patterns
130153
local elab "example_combo_tactic" : tactic => do
131154
let goal ← getGoalProp
132-
let hyps ← getHypotheses
155+
let hyps ← getHypothesesProp
133156
if let ~q($x /\ $y) := goal then
134157
if ← Lean.Meta.isExprDefEq x y then
135158
-- x /\ x -> x
@@ -167,7 +190,7 @@ def applyIn (name: Lean.Ident) (t: Lean.Elab.Tactic.TacticM (Lean.TSyntax `term)
167190
return ()
168191

169192
local elab "example_applyin_tactic" : tactic => do
170-
let hyps ← getHypotheses
193+
let hyps ← getHypothesesProp
171194
for (name, ty) in hyps do
172195
match ty with
173196
| ~q((((($a : Prop)) → $b)) /\ ($a')) =>

0 commit comments

Comments
 (0)