Zulip Chat Archive
Stream: lean4
Topic: How to call the declaration elaborator
Simon Hudon (Feb 12 2022 at 16:36):
Note: in the process of writing up this question, I found the answer but I think it was an interesting problem and I thought I'd share the problem and the solution here.
I'm defining a command syntax for opaque definitions. I'm defining the parser by calling the «def»
parser and my elaborator begins calling the declaration elaborator on the (slightly massaged) syntax tree.
I get into a funny situation where the declaration elaborator fails when the definition has a non-atomic (e.g. foo.bar
) name. However the Lean syntax does allow such definitions. Am I missing a step where the name has to be expanded?
import Lean.Elab.Declaration
namespace Lean
namespace Parser
namespace Command
open Elab.Command
syntax (name := opaqueDef)
declModifiers "opaque " «def» : command
@[commandElab opaqueDef]
def elabOpaqueDef : CommandElab := λ stx => do
let mods := stx[0]
let kw := stx[1]
let «def» := stx[2]
print_vars![«def».getKind, stx.getKind]
let stx := stx.setArgs #[mods, «def»]
Lean.Elab.Command.elabDeclaration stx
opaque def x := 3 -- works
def x.x := 3 -- works
opaque def x.y := 3 -- does not works
-- Error: atomic identifier expected 'x.y'
(solution coming in a moment)
Simon Hudon (Feb 12 2022 at 16:50):
There are two problems with the way my code just plainly calls elabDeclaration
on my home made declaration syntax:
-
Minor problem: it does not set the kind of the node.
elabDeclaration
checks the kind to see which one of``Lean.Parser.Command.«def»
or``Lean.Parser.Command.«instance»
etc. -
While
elabDeclaration
does handle namespace expansion, when it encounters a complex name, after it rewrites the syntax tree with the right constructs (anamespace
command and a declaration with an atomic name), it callselabCommand
on it which starts the elaboration all over again. In my code, I rewrite the syntax tree to make it more digestible byelabDeclaration
by removing the keywordopaque
. That means that restarting the elaboration does not end up calling my own elaborator.
The consequence for the #mwe I showed is that, I created a syntax tree that I thought would be more digestible
Simon Hudon (Feb 12 2022 at 16:56):
Here is what the code snippet becomes:
Fixing namespace expansion
Explanation
Leonardo de Moura (Feb 12 2022 at 17:06):
@Simon Hudon The key problem in your example is that you are constructing an invalid syntax tree at
let stx := stx.setArgs #[mods, «def»]
If you create a proper declaration
syntax object, everything works.
import Lean.Elab.Declaration
namespace Lean
namespace Parser
namespace Command
open Elab.Command
syntax (name := opaqueDef)
declModifiers "opaque " «def» : command
@[commandElab opaqueDef]
def elabOpaqueDef : CommandElab := λ stx => do
let mods := stx[0]
let kw := stx[1]
let «def» := stx[2]
let stx := mkNode ``Lean.Parser.Command.declaration #[mods, «def»] -- <<< FIxed here
Lean.Elab.Command.elabDeclaration stx
opaque def x := 3 -- works
def x.x := 3 -- works
opaque def x.y := 3 -- works
Simon Hudon (Feb 12 2022 at 17:08):
In this context, that's true but if I need to do something special during elaboration because of the opaque
keyword, when elabDeclaration
calls elabCommand
, it will not see the opaque
keyword anymore.
Simon Hudon (Feb 12 2022 at 17:10):
Addendum: ok, I see how to get around that. In hindsight, it looks like more fuss than was needed. Sorry about that
Simon Hudon (Feb 12 2022 at 17:12):
Thanks for your help!
Gabriel Ebner (Feb 14 2022 at 09:54):
@Simon Hudon you might be interested in https://github.com/leanprover-community/mathlib4/blob/89fab7c0c4b59709dbafe212a9e02261c73b7d09/Mathlib/Tactic/IrreducibleDef.lean
Simon Hudon (Feb 14 2022 at 16:50):
Nice! Thanks! My version does something similar and also transports the equations produced by the equation compiler. It does not register them as equations but they can still be useful
Simon Hudon (Feb 14 2022 at 16:52):
I'm also preparing a feature where writing:
opaque namespace MyOpaqueDef
...
end MyOpaqueDef
lets you write definitions in terms of your definition as if it was not opaque (as long as the types work out when you transport them)
Last updated: Dec 20 2023 at 11:08 UTC