Zulip Chat Archive
Stream: lean4
Topic: Pass optional syntax in macro
Patrick Massot (Jul 15 2023 at 15:18):
In the following code, a call to tactic bar
is meant to expand to the same call to foo
. But I don't know how to pass the optional syntax. Both variations below fail.
open Lean Parser Tactic
macro "foo" (location)? : tactic => `(tactic|done)
macro "bar" loc:(location)? : tactic => `(tactic|foo $loc)
macro "bar" loc:(location)? : tactic => `(tactic|foo $(mkOptionalNode loc))
Mac Malone (Jul 15 2023 at 15:32):
@Patrick Massot $[...]?
is used for optional syntax:
macro "bar" loc?:(location)? : tactic => `(tactic|foo $[$loc?]?)
Patrick Massot (Jul 15 2023 at 15:37):
Thanks a lot. It almost work in my real use case. It fails in the presence of a mysterious &
in the original syntax;
Patrick Massot (Jul 15 2023 at 15:38):
Something like
macro "foo" (&"baz")? (location)? : tactic => `(tactic|done)
macro "bar" ba:(&"baz")? loc:(location)? : tactic => `(tactic|foo $[$ba]? $[$loc]?)
Sebastian Ullrich (Jul 15 2023 at 15:53):
The syntax for individual tokens is a bit different
macro "bar" ba:(&"baz")? loc:(location)? : tactic => `(tactic|foo $[baz%$ba]? $[$loc]?)
Patrick Massot (Jul 15 2023 at 16:00):
Thanks!
Patrick Massot (Jul 15 2023 at 16:21):
Next I need to remember how to write a macro which expand to several tactic calls, fighting the difference between tactic
and tactic_seq
.
Patrick Massot (Jul 15 2023 at 16:22):
Say I want to add done
after foo $[baz%$ba]? $[$loc]?
, how do I do that?
Sebastian Ullrich (Jul 15 2023 at 16:24):
You can use parentheses to turn a tactic sequence into a single tactic
Patrick Massot (Jul 15 2023 at 16:25):
I knew there was a simple trick but I couldn't remember it. Thanks!
Patrick Massot (Nov 03 2023 at 00:45):
I hit again the same issue as in July but I can't get the above answer to work. If have a tactic whose definition starts with
elab tok:"rw_ineq" rules:rwRuleSeq loc:(location)? withArg:((" with " (colGt binderIdent)+)?) : tactic =>
and I want a macro rwa_ineq
with the exact same syntax that call rw_ineq
and then assumption
. I tried
macro "rwa_ineq " rws:rwRuleSeq loc:(location)? withArg:(" with " (colGt binderIdent)+)? : tactic =>
`(tactic| (rw_ineq $rws:rwRuleSeq $[$loc:location]? $[$withArg:location]?; assumption))
but that doesn't work.
Full code is
import Lean
open Lean Parser Meta Elab Term Tactic
elab tok:"rw_ineq" rules:rwRuleSeq loc:(location)? withArg:((" with " (colGt Lean.binderIdent)+)?) : tactic =>
pure ()
macro "rwa_ineq " rws:rwRuleSeq loc:(location)? withArg:(" with " (colGt Lean.binderIdent)+)? : tactic =>
`(tactic| (rw_ineq $rws:rwRuleSeq $[$loc:location]? $[$withArg:location]?; assumption))
Kyle Miller (Nov 03 2023 at 00:56):
Here's one way:
import Lean
open Lean Parser Meta Elab Term Tactic
syntax withClause := " with " (colGt Lean.binderIdent)?
elab tok:"rw_ineq" rules:rwRuleSeq loc:(location)? withArg:(withClause)? : tactic =>
pure ()
macro "rwa_ineq " rws:rwRuleSeq loc:(location)? withArg:(withClause)? : tactic =>
`(tactic| (rw_ineq $rws:rwRuleSeq $[$loc:location]? $[$withArg]?; assumption))
Kyle Miller (Nov 03 2023 at 00:58):
Here's another:
import Lean
open Lean Parser Meta Elab Term Tactic
elab tok:"rw_ineq" rules:rwRuleSeq loc:(location)? withArg:((" with " (colGt Lean.binderIdent)+)?) : tactic =>
pure ()
syntax "rwa_ineq " rwRuleSeq (location)? (" with " (colGt Lean.binderIdent)+)? : tactic
macro_rules
| `(tactic| rwa_ineq $rws $[$loc]? $[with $args*]?) =>
`(tactic| rw_ineq $rws $[$loc]? $[with $args*]?)
Patrick Massot (Nov 03 2023 at 01:00):
Great, the first solution works (with minor ajustements to the code)! Thanks!
Patrick Massot (Nov 03 2023 at 01:01):
I'm still curious to understand why my original code didn't work (and it would be really great to have any of this documented somewhere).
Last updated: Dec 20 2023 at 11:08 UTC