Zulip Chat Archive
Stream: lean4
Topic: Lean4 AST
Bhakti Shah (Jan 11 2023 at 04:51):
is there a way to extract the AST for a particular source file? I think I saw something about lean3 having an AST fork where you could pass --ast
as an argument, but does something similar exist for lean4?
apologies if this is documented somewhere, I couldn't really find anything
Mario Carneiro (Jan 11 2023 at 07:24):
lean 4 has much better out of the box support for AST traversal, so the hack that was done to lean 3 is not really necessary anymore. lean files parse into objects of type Syntax
and you can just write that out as JSON if you want
Bhakti Shah (Jan 11 2023 at 22:09):
Mario Carneiro
lean files parse into objects of type
Syntax
and you can just write that out as JSON if you want
I see -- so the .ilean
file is basically the AST, can't believe it was that simple, I just never thought to look there. Is there any known documentation on the grammar other than the Parser
directory in the source code?
Mario Carneiro (Jan 11 2023 at 22:53):
the grammar is extensible, so no not really, it's context sensitive and defined by the syntax
lines that have occurred so far
Sebastian Ullrich (Jan 12 2023 at 08:36):
The syntax trees are not persisted. .ilean
is just a serialization of docs4#Lean.Server.Ilean, no syntax trees there.
Bhakti Shah (Jan 13 2023 at 01:23):
I see -- my bad, didn't look closely enough
is there a way to extract the syntax object from a program, then? sorry if these are super basic, I'm more of a coq user
Alex Keizer (Jan 13 2023 at 06:29):
I don't know if there's a more elegant way, but this (mostly) works
import Lean
open Lean.Elab
open Lean.Elab.Command
elab "dbg" cmd:command+ : command => do
for cmd in cmd do
dbg_trace "\n{cmd}\n\n"
elabCommand cmd
It does slightly change the meaning of the commands, since parsing and elaboration are now no longer interspersed, all parsing happens at the start, so this will break if you define and directly use parser extensions in the code you're examining
Mario Carneiro (Jan 13 2023 at 06:48):
Here's another trick to get the commands, using a linter and a global variable:
Test/SpySyntax.lean
:
import Lean
initialize syntaxes : IO.Ref (Array Lean.Syntax) ← IO.mkRef #[]
initialize Lean.addLinter fun stx => syntaxes.modify (·.push stx)
Test.lean
:
import Test.SpySyntax
open Lean
set_option pp.rawOnError true
elab "foo" : tactic => do
for stx in ← syntaxes.get do
try logInfo m!"{← PrettyPrinter.formatCommand stx}"
catch _ => pure ()
syntaxes.set #[]
example : True := by foo
Mario Carneiro (Jan 13 2023 at 06:49):
The "right" way to do this is to use a custom driver based on runFrontend
. That will allow you to get the AST for any file without modifying the target file
Bhakti Shah (Jan 14 2023 at 18:51):
Thank you! I'll start with these and probably try to work my way up to the "right" way
Last updated: Dec 20 2023 at 11:08 UTC