Zulip Chat Archive

Stream: lean4

Topic: elab `foo with x y`


David Renshaw (Oct 21 2022 at 20:07):

import Lean

open Lean Elab.Tactic

elab (name := foo) "foo " withArg:(" with " (colGt binderIdent)+)? : tactic =>
  do dbg_trace withArg
     pure ()

example : True := by
  foo with x y z -- prints `none`
  exact True.intro

why does this print none? I expect it to print the with x y z syntax.

David Renshaw (Oct 21 2022 at 20:08):

A similar thing apparently does work for the cases tactic: https://github.com/leanprover-community/mathlib4/blob/63a677d81af026760e1f530bb588696a123835c0/Mathlib/Tactic/Cases.lean#L93

David Renshaw (Oct 21 2022 at 20:10):

Aha!
Just needed more parens, seemingly:

elab (name := foo) "foo " withArg:((" with " (colGt binderIdent)+)?) : tactic =>
  do dbg_trace withArg
     pure ()

David Renshaw (Oct 21 2022 at 20:11):

I guess the ? binds less tightly than I was assuming it did.

Mario Carneiro (Oct 21 2022 at 21:03):

No, the parens are not about precedence there

Mario Carneiro (Oct 21 2022 at 21:15):

This looks like a bug in the macro parser (cc: @Sebastian Ullrich ): because the withArg nested parser has arity 2 (" with " (colGt binderIdent)+), calling getOptional? on it in the macro code yields none instead of the expected data

Mario Carneiro (Oct 21 2022 at 21:16):

it's possible that the macro can't do anything about it though since ATM parser arities are not known at compile time

Mario Carneiro (Oct 21 2022 at 21:18):

you should just not use elab for this and use a separate syntax / elab_rules:

syntax (name := foo) "foo " (" with " (colGt binderIdent)+)? : tactic
elab_rules : tactic
  | `(tactic| foo $[with $withArg*]?) => do
    dbg_trace withArg

David Renshaw (Oct 21 2022 at 21:19):

The (colGt binderIdent)+ -> $withArg* part there is surprising to me. The plus turns into a star?

Mario Carneiro (Oct 21 2022 at 21:19):

yes, there is no + modifier in patterns

Mario Carneiro (Oct 21 2022 at 21:20):

since they both bind as TSyntaxArray

Mario Carneiro (Oct 21 2022 at 21:20):

maybe we should add it just as a synonym to make things look more regular (no pun intended)

David Renshaw (Oct 21 2022 at 21:21):

I think that might be where I got stuck when I tried to do an elab_rules for this earlier.

David Renshaw (Oct 21 2022 at 21:21):

But it makes sense now that you explained it.

Sebastian Ullrich (Oct 22 2022 at 08:00):

Mario Carneiro said:

This looks like a bug in the macro parser (cc: Sebastian Ullrich ): because the withArg nested parser has arity 2 (" with " (colGt binderIdent)+), calling getOptional? on it in the macro code yields none instead of the expected data

Ah, hm, https://github.com/leanprover/lean4/blob/c672046767611565b84729db06a7c416625591b4/src/Lean/Elab/MacroArgUtil.lean#L39-L41

Sebastian Ullrich (Oct 22 2022 at 08:00):

The intention indeed was that macro/elab should only be used for "simple" arguments

Mario Carneiro (Oct 22 2022 at 08:05):

we assume the user knows what they are doing

famous last words

Sebastian Ullrich (Oct 22 2022 at 08:06):

It's not really for trust in the user but for lack of better options

Mario Carneiro (Oct 22 2022 at 08:06):

I think even a panic would be better than just returning none

Mario Carneiro (Oct 22 2022 at 08:07):

with this version, you have to go debugging to figure out what's wrong

Sebastian Ullrich (Oct 22 2022 at 08:40):

In theory we now have all the information we need to statically check this https://github.com/leanprover/lean4/pull/1229


Last updated: Dec 20 2023 at 11:08 UTC