Zulip Chat Archive

Stream: lean4

Topic: Get theorem statement as string


Jon Eugster (May 16 2023 at 19:28):

How can I extract a String of the form add_zero (n : Nat) : n + 0 = n or just (n : Nat) : n + 0 = n from a defined theorem add_zero? I tried the following:

import Lean

open Lean Meta Elab Command

theorem add_zero (n : Nat) : n + 0 = n := rfl

-- copied from `#check`
def magic (term : Ident) : CommandElabM MessageData := do
  let c := term.getId
  addCompletionInfo <| .id term c (danglingDot := false) {} none
  return (.ofPPFormat { pp := fun
    | some ctx => ctx.runMetaM <| PrettyPrinter.ppSignature c
    | none     => return f!"{c}"  -- should never happen
  })

elab "Test" name:ident : command => do
  logInfoAt name ( magic name)
  logInfoAt name ( ( magic name).toString)

Test add_zero

-- MWE.lean:25:5
--   add_zero (n : Nat) : n + 0 = n  -- `MessageData` looks good in VSCode


-- MWE.lean:25:5
--   add_zero   -- But `.toString` does not do what I want.

The MessageData looks correct, but I can't turn that into a String without loosing the type.

(I want to pack this into a JSON, that's why I think I need String rather than MessageData)

Kyle Miller (May 16 2023 at 20:00):

The main function here is getTypeString

import Lean

open Lean Meta Elab Command

theorem add_zero (n : Nat) : n + 0 = n := rfl

-- Copied somewhat from PrettyPrinter.ppSignature
def getTypeString (name : Name) : MetaM String := do
  let decl  getConstInfo name
  let e := Expr.const name (decl.levelParams.map mkLevelParam)
  let (stx, _stx)  PrettyPrinter.delabCore e (delab := PrettyPrinter.Delaborator.delabConstWithSignature)
  let f  PrettyPrinter.ppTerm stx -- HACK: not a term
  return toString f

-- copied from `#check`
def magic (term : Ident) : CommandElabM Unit := do
  try
    for c in ( resolveGlobalConstWithInfos term) do
      addCompletionInfo <| .id term c (danglingDot := false) {} none
      logInfoAt term <| .ofPPFormat { pp := fun
        | some ctx => ctx.runMetaM <| getTypeString c
        | none     => return f!"{c}"  -- should never happen
      }
  catch _ => throwError "failure in magic"


elab "Test" name:ident : command => do
  magic name

Test add_zero
-- add_zero (n : Nat) : n + 0 = n

Kyle Miller (May 16 2023 at 20:02):

Here's a simpler function:

def getTypeString (name : Name) : MetaM String := do
  let decl  getConstInfo name
  let ty  ppExpr decl.type
  return toString name ++ " : " ++ toString ty

Rather than the fancy one that puts arguments before the colon, this one gives types like add_zero : ∀ (n : Nat), n + 0 = n

Jon Eugster (May 16 2023 at 20:12):

Thanks Kyle!

Sebastian Ullrich (May 16 2023 at 20:16):

The problem with your original code is that ctx is indeed none, which you can fix by wrapping the message in addMessageContextPartial

Jon Eugster (May 16 2023 at 20:22):

I have to go back on the computer to understand that... where did Kyle's first solution get its ctx back?

Kyle Miller (May 16 2023 at 20:24):

The ctx comes from when the MessageData is finally formatted for the infoview; this .ofPPFormat constructor is for deferring pretty printing until you have such a context. (At least this is my understanding -- I've never really looked at it until now!)

Kyle Miller (May 16 2023 at 20:25):

The problem with the original magic function is that it tries to format the data immediately, so it's not yet in a context with a ctx.

Jon Eugster (May 16 2023 at 21:37):

I understand now what happened, thanks!


Last updated: Dec 20 2023 at 11:08 UTC