-
Notifications
You must be signed in to change notification settings - Fork 450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: use sepBy1Indent for tactic and conv blocks #1612
Conversation
I had to do a slightly ugly bootstrapping hack in 4657b74. The issue is that parser aliases (such as |
[Elab.step] | ||
skip | ||
trivial | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the formatter regressed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fun. It turns out that tacticSeq
now parses the trailing newline (after trivial
) as a separator. And the formatter then prints this final newline-separator. We might want to change the formatter to drop the final separator if it's a newline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final newline tweak implemented.
I suspect many will view this change as an extra plus :) |
After this PR, it will be a very small change to enforce uniform start columns in tactic blocks (and |
-- `argNew` is `arg` as singleton sequence. The idea is to make sure it does not satisfy `isCheckpointableTactic` anymore | ||
let argNew := arg.setArg 0 (mkNullNode #[arg[0]]) | ||
let argNew := ⟨mkNullNode #[arg]⟩ -- HACK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please explain the "HACK"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a hack because it creates invalid syntax (see pretty-printer issues in the Zulip thread):
import Lean open Lean Elab Command PrettyPrinter
elab "run" : command => do
let tac ← `(tactic| simp)
let tac : TSyntax `tactic := ⟨mkNullNode #[tac]⟩ -- HACK: produces invalid tactic
let term ← `(by $tac:tactic)
logInfo (← liftCoreM do ppTerm term)
run -- unknown constant 'null'
let acc := acc.push argNew | ||
go (i+1) #[] (push acc result) | ||
else | ||
go (i+1) (acc.push arg) result | ||
else | ||
return result ++ acc | ||
|
||
/-- Evaluate `many (group (tactic >> optional ";")) -/ | ||
def evalManyTacticOptSemi (stx : Syntax) : TacticM Unit := do | ||
for seqElem in (← addCheckpoints stx.getArgs) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are converting here to Array Syntax.Tactic
. It is not clear to me why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Note: I have rewritten this function one more time since your comment.)
The general reason is that the AST of tactic sequences has changed from many1 (group (tactic >> optional ";"))
to sepBy1Indent tactic
, i.e. from [(group (skip) [])]
to [(skip) []]
. Having explicit types available (Array Syntax.Tactic
instead of Syntax
) makes the refactoring easier because the type system tells you what is a list of tactics, what is a tactic, etc., and you don't have to guess yourself what the Syntax
means.
At first it seemed like it was not necessary to keep the separators, making Array Syntax.Tactic
a natural choice.
I have now changed it back to untyped Syntax
because we need to preserve the separators. Ideally we'd have a TSepIndentArray
for this because the manual index calculations are not particularly pretty. (However that doesn't solve all problems either. Even the TSepArray
API is pretty bare-bones---and it doesn't preserve the separators either.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TSepIndentArray
Oh I completely forgot we had this already. It's called TSepArray `tactic ""
.
def evalManyTacticOptSemi (stx : Syntax) : TacticM Unit := do | ||
for seqElem in (← addCheckpoints stx.getArgs) do | ||
evalTactic seqElem[0] | ||
saveTacticInfoForToken seqElem[1] -- add TacticInfo node for `;` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not clear to me why we don't need this anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"this" here is the line saveTacticInfoForToken seqElem[1]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I understand. I thought this was subsumed by Sebastian's other tactic position tweaks. And the tests passed (including the ones checking tactic states at semicolons), so this was plausible.
But it turns out this was indeed necessary, but only for the space after the semicolon... I'm adding a test.
tac1; tac2
--^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding more tests is great. I am frequently worried about changes that affect the infoview because of the lack of tests.
72b7ec0
to
c66f98d
Compare
c66f98d
to
4ebeb7d
Compare
Re: saving tactic info at separators. This prevents the regression with syntax "mytac" tacticSeq : tactic
macro_rules
| `(tactic| mytac $[$tacs]*) => `(tactic| { $tacs* })
example : True ∨ True := by
mytac constructor; constructor
-- still has the issue with the space after the semicolon We should probably fix this somewhere else. |
Thanks for the changes. I will go over the code tomorrow, and try to merge it. If I am still confused, we can discuss during the dev meeting. |
This is the first step towards using
colEq
in tactic/conv blocks, addressing #1606.The main user-visible change is that
by simp rfl
(without newline or semicolon) is no longer supported.