Zulip Chat Archive

Stream: lean4

Topic: Macros to get source location


Chris Bailey (Jul 17 2025 at 20:52):

Rust has a family of utility macros line!(), column!(), and file!() that expand to the line, column, and file where they're invoked. These are useful for things like error reporting, say you want to communicate what branch of a function failed in a way that's easily jumped to by someone debugging a problem. I couldn't find a direct analog so I took a stab at it, does anyone have any suggestions/improvements, particularly on the file! one? It seems like these can't just be macros because they need MonadLog and IO.

-- Seems to work; should print the source file path starting from the project root.
elab "file!" : term => do
  let curFile  getFileName
  let xs := ( Lean.getSrcSearchPath).filterMap (curFile.dropPrefix? ·.toString)
  let truncdFileName :=
    match xs with
    | [] => curFile
    | hd :: tl =>
      let out := tl.foldl (init := hd) (fun sink next =>
        if Substring.bsize next < Substring.bsize sink then next else sink
      ) |>.toString
      if out.startsWith "/"
      then out.drop 1
      else out
  return toExpr truncdFileName

elab "line!" : term => do
  return toExpr ( Lean.getRefPosition).line

elab "column!" : term => do
  return toExpr ( Lean.getRefPosition).column

elab "position!" : term => do
  return toExpr ( Lean.getRefPosition)

Aaron Liu (Jul 17 2025 at 21:02):

The panic! macro expands to contain the file, line, and column it's written, as well as the name of the function it's in, maybe you can see how it works

Chris Bailey (Jul 17 2025 at 21:20):

That's a good thought. panic! uses Lean.Environment.mainModule which is probably a better bet.


Last updated: Dec 20 2025 at 21:32 UTC