Zulip Chat Archive
Stream: lean4
Topic: Print different goals when the cursor is scanning a tactic
Simon Hudon (Apr 12 2022 at 04:03):
In Lean 3, the parser of rw
is implemented so that when you move your cursor through the rewrite rules, you see each intermediate goal. It's a pretty cool feature! Is there something similar in Lean 4?
Sebastian Ullrich (Apr 12 2022 at 08:26):
Does it not work for you? It should work basically the same.
Simon Hudon (Apr 12 2022 at 16:35):
Sorry I wasn't clear. I mean what if I want to use the same feature for a tactic that I'm implementing, how do I do that?
Sebastian Ullrich (Apr 12 2022 at 16:41):
Haha, that makes more sense! The interesting parts of the implementation are here: https://github.com/leanprover/lean4/blob/3bdb385c199ebbcc2070f8849647df35c2cc2145/src/Lean/Elab/Tactic/Rewrite.lean#L34-L41
withTacticInfoContext
will record the tactic state before and after running the last argument, and then annotate the lexical range of the given syntax tree with that info. mkNullNode
is used here to create a synthetic syntax tree whose lexical range spans two given syntax trees.
Simon Hudon (Apr 12 2022 at 17:43):
Nice! Thanks!
Simon Hudon (Apr 13 2022 at 01:32):
It's mostly working. I'm implementing ssreflect's move
tactic and tactical and I want to show the goal between patterns. In this context, move => a b c
is the same as intros a b c
. I get the following odd behavior:
move => a b c
^
-- ⊢ T → V → U → True
move => a b c
^
⊢ T → V → U → True
u : T
⊢ V → U → True
Here is my elaboration code:
elab_rules : tactic
| `(tactic| $tac => $pats*) => do
let pats' ← pats.mapM parseMoveIntroPat
evalTactic tac
let arrow := (← getRef)[1]
withTacticInfoContext (mkNullNode #[arrow, pats[0]]) (pure ())
for i in [:pats.size], pat in pats' do
let next := pats.getD (i+1) Syntax.missing
withTacticInfoContext (mkNullNode #[pats[i], next]) <|
allGoals <| runMoveIntroPat pat
Can you see why in the second position I have two goals getting displayed?
Mario Carneiro (Apr 13 2022 at 03:23):
Simon Hudon (Apr 13 2022 at 03:42):
Ok, I figured it out. I was treating the mkNullNode
as an interval. It's more like a syntax tree or a set of syntax trees where we want a specific goal to be displayed. So my code should be (this time it's a #mwe, sorry about the oversight):
import Lean.Elab.Tactic
open Lean.Meta Lean.Elab.Tactic Lean
syntax "move" " => " ident+ : tactic
elab_rules : tactic
| `(tactic| move => $pats*) =>
withMainContext do
let kw := (← getRef)[0]
let arrow := (← getRef)[1]
withTacticInfoContext (mkNullNode #[kw, arrow]) (pure ())
for pat in pats do
withTacticInfoContext pat do
let (_, g) ←
liftMetaMAtMain (intro . pat.getId)
replaceMainGoal [g]
theorem foo : α → β → γ → θ := by
move => u v w
Simon Hudon (Apr 13 2022 at 03:43):
This time, each variable has only one goal
Mario Carneiro (Apr 13 2022 at 05:29):
what is the purpose of the first withTacticInfoContext
? It doesn't seem to make any difference
Mario Carneiro (Apr 13 2022 at 05:32):
also you can do
| `(tactic| move%$kw =>%$arrow $pats*) =>
instead of that getRef
stuff
Simon Hudon (Apr 13 2022 at 13:48):
Thanks for the neat trick! withTacticInfoContext
is from @Sebastian Ullrich 's code snippet. The idea is to implement the same feature that rw
has where you can move your cursor over the the rewrite rules and see the intermediate proof states. withTacticInfoContext
records those proof states and associates them with the syntax trees that you're giving it.
Mario Carneiro (Apr 13 2022 at 15:56):
Yes I understand that. I'm saying that I don't see any difference in the goal states with or without that line
Mario Carneiro (Apr 13 2022 at 15:57):
the second withTacticInfoContext
seems to be working as intended but you get the behavior you want even if you delete the first withTacticInfoContext
Simon Hudon (Apr 13 2022 at 16:17):
Ah, right! Yeah, I'm not clear on that. @Sebastian Ullrich, what's the purpose of the first withTacticInfoContext
in the rw
implementation?
Sebastian Ullrich (Apr 13 2022 at 16:22):
I believe this was from before we refined the behavior for when to show the pre/post state
Simon Hudon (Apr 13 2022 at 16:29):
Ok. What did it used to do and what did it get changed to?
Last updated: Dec 20 2023 at 11:08 UTC