Skip to content

Commit

Permalink
feat: Lean.Expr.name? (#5760)
Browse files Browse the repository at this point in the history
Adds a recognizer for `Name` literal expressions. Handles `Name`
constructors as well as the `Lean.Name.mkStr*` functions.
  • Loading branch information
kmill authored Oct 18, 2024
1 parent 1d66ff8 commit fd15d8f
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 23 deletions.
23 changes: 1 addition & 22 deletions src/Lean/PrettyPrinter/Delaborator/Builtins.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1215,32 +1215,11 @@ def delabDo : Delab := whenPPOption getPPNotation do
let items ← elems.toArray.mapM (`(doSeqItem|$(·):doElem))
`(do $items:doSeqItem*)

def reifyName : Expr → DelabM Name
| .const ``Lean.Name.anonymous _ => return Name.anonymous
| mkApp2 (.const ``Lean.Name.str _) n (.lit (.strVal s)) => return (← reifyName n).mkStr s
| mkApp2 (.const ``Lean.Name.num _) n (.lit (.natVal i)) => return (← reifyName n).mkNum i
| mkApp (.const ``Lean.Name.mkStr1 _) (.lit (.strVal a)) => return Lean.Name.mkStr1 a
| mkApp2 (.const ``Lean.Name.mkStr2 _) (.lit (.strVal a1)) (.lit (.strVal a2)) =>
return Lean.Name.mkStr2 a1 a2
| mkApp3 (.const ``Lean.Name.mkStr3 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) =>
return Lean.Name.mkStr3 a1 a2 a3
| mkApp4 (.const ``Lean.Name.mkStr4 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) =>
return Lean.Name.mkStr4 a1 a2 a3 a4
| mkApp5 (.const ``Lean.Name.mkStr5 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) =>
return Lean.Name.mkStr5 a1 a2 a3 a4 a5
| mkApp6 (.const ``Lean.Name.mkStr6 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) (.lit (.strVal a6)) =>
return Lean.Name.mkStr6 a1 a2 a3 a4 a5 a6
| mkApp7 (.const ``Lean.Name.mkStr7 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) (.lit (.strVal a6)) (.lit (.strVal a7)) =>
return Lean.Name.mkStr7 a1 a2 a3 a4 a5 a6 a7
| mkApp8 (.const ``Lean.Name.mkStr8 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) (.lit (.strVal a6)) (.lit (.strVal a7)) (.lit (.strVal a8)) =>
return Lean.Name.mkStr8 a1 a2 a3 a4 a5 a6 a7 a8
| _ => failure

@[builtin_delab app.Lean.Name.str,
builtin_delab app.Lean.Name.mkStr1, builtin_delab app.Lean.Name.mkStr2, builtin_delab app.Lean.Name.mkStr3, builtin_delab app.Lean.Name.mkStr4,
builtin_delab app.Lean.Name.mkStr5, builtin_delab app.Lean.Name.mkStr6, builtin_delab app.Lean.Name.mkStr7, builtin_delab app.Lean.Name.mkStr8]
def delabNameMkStr : Delab := whenPPOption getPPNotation do
let n ← reifyName (← getExpr)
let some n := (← getExpr).name? | failure
-- not guaranteed to be a syntactically valid name, but usually more helpful than the explicit version
return mkNode ``Lean.Parser.Term.quotedName #[Syntax.mkNameLit s!"`{n}"]

Expand Down
25 changes: 25 additions & 0 deletions src/Lean/Util/Recognizers.lean
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,29 @@ def arrayLit? (e : Expr) : Option (Expr × List Expr) :=
def prod? (e : Expr) : Option (Expr × Expr) :=
e.app2? ``Prod

/--
Checks if an expression is a `Name` literal, and if so returns the name.
-/
def name? : Expr → Option Name
| .const ``Lean.Name.anonymous _ => Name.anonymous
| mkApp2 (.const ``Lean.Name.str _) n (.lit (.strVal s)) => (name? n).map (·.str s)
| mkApp2 (.const ``Lean.Name.num _) n i =>
(i.rawNatLit? <|> i.nat?).bind fun i => (name? n).map (Name.num · i)
| mkApp (.const ``Lean.Name.mkStr1 _) (.lit (.strVal a)) => Lean.Name.mkStr1 a
| mkApp2 (.const ``Lean.Name.mkStr2 _) (.lit (.strVal a1)) (.lit (.strVal a2)) =>
Lean.Name.mkStr2 a1 a2
| mkApp3 (.const ``Lean.Name.mkStr3 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) =>
Lean.Name.mkStr3 a1 a2 a3
| mkApp4 (.const ``Lean.Name.mkStr4 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) =>
Lean.Name.mkStr4 a1 a2 a3 a4
| mkApp5 (.const ``Lean.Name.mkStr5 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) =>
Lean.Name.mkStr5 a1 a2 a3 a4 a5
| mkApp6 (.const ``Lean.Name.mkStr6 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) (.lit (.strVal a6)) =>
Lean.Name.mkStr6 a1 a2 a3 a4 a5 a6
| mkApp7 (.const ``Lean.Name.mkStr7 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) (.lit (.strVal a6)) (.lit (.strVal a7)) =>
Lean.Name.mkStr7 a1 a2 a3 a4 a5 a6 a7
| mkApp8 (.const ``Lean.Name.mkStr8 _) (.lit (.strVal a1)) (.lit (.strVal a2)) (.lit (.strVal a3)) (.lit (.strVal a4)) (.lit (.strVal a5)) (.lit (.strVal a6)) (.lit (.strVal a7)) (.lit (.strVal a8)) =>
Lean.Name.mkStr8 a1 a2 a3 a4 a5 a6 a7 a8
| _ => none

end Lean.Expr
2 changes: 1 addition & 1 deletion tests/lean/run/677.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def encodeDecode [ToJson α] [FromJson α] (x : α) : Except String α := do
let json := toJson x
fromJson? json

/-- info: Name.anonymous.num 5 -/
/-- info: `5 -/
#guard_msgs in
#eval IO.ofExcept <| encodeDecode (Name.mkNum Name.anonymous 5)

Expand Down

0 comments on commit fd15d8f

Please sign in to comment.