Skip to content

Commit 1d9dd33

Browse files
authored
feat: #print sig (#8641)
This PR adds the `#print sig $ident` variant of the `#print` command, which omits the body. This is useful for testing meta-code, in the ``` #guard_msgs (drop trace, all) in #print sig foo ``` idiom. The benefit over `#check` is that it shows the declaration kind, reducibility attributes (and in the future more built-in attributes, like `@[defeq]` in #8419). (One downside is that `#check` shows unused function parameter names, e.g. in induction principles; this could probably be refined.)
1 parent 9b9dd85 commit 1d9dd33

File tree

2 files changed

+60
-38
lines changed

2 files changed

+60
-38
lines changed

src/Lean/Elab/Print.lean

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,47 +23,57 @@ private def levelParamsToMessageData (levelParams : List Name) : MessageData :=
2323
return m ++ "}"
2424

2525
private def mkHeader (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (safety : DefinitionSafety) (sig : Bool := true) : CommandElabM MessageData := do
26-
let m : MessageData :=
27-
match (← getReducibilityStatus id) with
28-
| ReducibilityStatus.irreducible => "@[irreducible] "
29-
| ReducibilityStatus.reducible => "@[reducible] "
30-
| ReducibilityStatus.semireducible => ""
31-
let m :=
32-
m ++
33-
match safety with
34-
| DefinitionSafety.unsafe => "unsafe "
35-
| DefinitionSafety.partial => "partial "
36-
| DefinitionSafety.safe => ""
37-
let m := if isProtected (← getEnv) id then m ++ "protected " else m
38-
let (m, id) := match privateToUserName? id with
39-
| some id => (m ++ "private ", id)
40-
| none => (m, id)
26+
let mut attrs := #[]
27+
match (← getReducibilityStatus id) with
28+
| ReducibilityStatus.irreducible => attrs := attrs.push m!"irreducible"
29+
| ReducibilityStatus.reducible => attrs := attrs.push m!"reducible"
30+
| ReducibilityStatus.semireducible => pure ()
31+
32+
let mut m : MessageData := m!""
33+
unless attrs.isEmpty do
34+
m := m ++ "@[" ++ MessageData.joinSep attrs.toList ", " ++ "] "
35+
36+
match safety with
37+
| DefinitionSafety.unsafe => m := m ++ "unsafe "
38+
| DefinitionSafety.partial => m := m ++ "partial "
39+
| DefinitionSafety.safe => pure ()
40+
41+
if isProtected (← getEnv) id then
42+
m := m ++ "protected "
43+
44+
let id' ← match privateToUserName? id with
45+
| some id' =>
46+
m := m ++ "private "
47+
pure id'
48+
| none =>
49+
pure id
50+
4151
if sig then
42-
return m!"{m}{kind} {id}{levelParamsToMessageData levelParams} : {type}"
52+
return m!"{m}{kind} {id'}{levelParamsToMessageData levelParams} : {type}"
4353
else
4454
return m!"{m}{kind}"
4555

46-
private def mkHeader' (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (isUnsafe : Bool) (sig : Bool := true) : CommandElabM MessageData :=
47-
mkHeader kind id levelParams type (if isUnsafe then DefinitionSafety.unsafe else DefinitionSafety.safe) (sig := sig)
48-
4956
private def mkOmittedMsg : Option Expr → MessageData
5057
| none => "<not imported>"
5158
| some e => e
5259

53-
private def printDefLike (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (value? : Option Expr) (safety := DefinitionSafety.safe) : CommandElabM Unit := do
54-
let m ← mkHeader kind id levelParams type safety
55-
let m := m ++ " :=" ++ Format.line ++ mkOmittedMsg value?
56-
logInfo m
60+
private def printAxiomLike (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (safety : DefinitionSafety) : CommandElabM Unit := do
61+
logInfo (← mkHeader kind id levelParams type safety)
5762

58-
private def printAxiomLike (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (isUnsafe := false) : CommandElabM Unit := do
59-
logInfo (← mkHeader' kind id levelParams type isUnsafe)
63+
private def printDefLike (sigOnly : Bool) (kind : String) (id : Name) (levelParams : List Name) (type : Expr) (value? : Option Expr) (safety := DefinitionSafety.safe) : CommandElabM Unit := do
64+
if sigOnly then
65+
printAxiomLike kind id levelParams type safety
66+
else
67+
let m ← mkHeader kind id levelParams type safety
68+
let m := m ++ " :=" ++ Format.line ++ mkOmittedMsg value?
69+
logInfo m
6070

6171
private def printQuot (id : Name) (levelParams : List Name) (type : Expr) : CommandElabM Unit := do
62-
printAxiomLike "Quotient primitive" id levelParams type
72+
printAxiomLike "Quotient primitive" id levelParams type (safety := DefinitionSafety.safe)
6373

6474
private def printInduct (id : Name) (levelParams : List Name) (numParams : Nat) (type : Expr)
6575
(ctors : List Name) (isUnsafe : Bool) : CommandElabM Unit := do
66-
let mut m ← mkHeader' "inductive" id levelParams type isUnsafe
76+
let mut m ← mkHeader "inductive" id levelParams type (if isUnsafe then .unsafe else .safe)
6777
m := m ++ Format.line ++ "number of parameters: " ++ toString numParams
6878
m := m ++ Format.line ++ "constructors:"
6979
for ctor in ctors do
@@ -89,7 +99,7 @@ private partial def printStructure (id : Name) (levelParams : List Name) (numPar
8999
(isUnsafe : Bool) : CommandElabM Unit := do
90100
let env ← getEnv
91101
let kind := if isClass env id then "class" else "structure"
92-
let header ← mkHeader' kind id levelParams type isUnsafe (sig := false)
102+
let header ← mkHeader kind id levelParams type (if isUnsafe then .unsafe else .safe) (sig := false)
93103
let levels := levelParams.map Level.param
94104
liftTermElabM <| forallTelescope (← getConstInfo id).type fun params _ =>
95105
let s := Expr.const id levels
@@ -158,20 +168,20 @@ private partial def printStructure (id : Name) (levelParams : List Name) (numPar
158168
withOptions (fun opts => opts.set pp.proofs.name false) do
159169
logInfo m
160170

161-
private def printIdCore (id : Name) : CommandElabM Unit := do
171+
private def printIdCore (sigOnly : Bool) (id : Name) : CommandElabM Unit := do
162172
let env ← getEnv
163173
match env.find? id with
164174
| ConstantInfo.axiomInfo { levelParams := us, type := t, isUnsafe := u, .. } =>
165175
match getOriginalConstKind? env id with
166-
| some .defn => printDefLike "def" id us t none (if u then .unsafe else .safe)
167-
| some .thm => printDefLike "theorem" id us t none (if u then .unsafe else .safe)
168-
| _ => printAxiomLike "axiom" id us t u
169-
| ConstantInfo.defnInfo { levelParams := us, type := t, value := v, safety := s, .. } => printDefLike "def" id us t v s
170-
| ConstantInfo.thmInfo { levelParams := us, type := t, value := v, .. } => printDefLike "theorem" id us t v
171-
| ConstantInfo.opaqueInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "opaque" id us t u
176+
| some .defn => printDefLike sigOnly "def" id us t none (if u then .unsafe else .safe)
177+
| some .thm => printDefLike sigOnly "theorem" id us t none (if u then .unsafe else .safe)
178+
| _ => printAxiomLike "axiom" id us t (if u then .unsafe else .safe)
179+
| ConstantInfo.defnInfo { levelParams := us, type := t, value := v, safety := s, .. } => printDefLike sigOnly "def" id us t v s
180+
| ConstantInfo.thmInfo { levelParams := us, type := t, value := v, .. } => printDefLike sigOnly "theorem" id us t v
181+
| ConstantInfo.opaqueInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "opaque" id us t (if u then .unsafe else .safe)
172182
| ConstantInfo.quotInfo { levelParams := us, type := t, .. } => printQuot id us t
173-
| ConstantInfo.ctorInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "constructor" id us t u
174-
| ConstantInfo.recInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "recursor" id us t u
183+
| ConstantInfo.ctorInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "constructor" id us t (if u then .unsafe else .safe)
184+
| ConstantInfo.recInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "recursor" id us t (if u then .unsafe else .safe)
175185
| ConstantInfo.inductInfo { levelParams := us, numParams, type := t, ctors, isUnsafe := u, .. } =>
176186
if isStructure env id then
177187
printStructure id us numParams t ctors[0]! u
@@ -182,13 +192,23 @@ private def printIdCore (id : Name) : CommandElabM Unit := do
182192
private def printId (id : Syntax) : CommandElabM Unit := do
183193
addCompletionInfo <| CompletionInfo.id id id.getId (danglingDot := false) {} none
184194
let cs ← liftCoreM <| realizeGlobalConstWithInfos id
185-
cs.forM printIdCore
195+
cs.forM (printIdCore (sigOnly := false) ·)
186196

187197
@[builtin_command_elab «print»] def elabPrint : CommandElab
188198
| `(#print%$tk $id:ident) => withRef tk <| printId id
189199
| `(#print%$tk $s:str) => logInfoAt tk s.getString
190200
| _ => throwError "invalid #print command"
191201

202+
private def printIdSig (id : Syntax) : CommandElabM Unit := do
203+
addCompletionInfo <| CompletionInfo.id id id.getId (danglingDot := false) {} none
204+
let cs ← liftCoreM <| realizeGlobalConstWithInfos id
205+
cs.forM (printIdCore (sigOnly := true) ·)
206+
207+
@[builtin_command_elab «printSig»] def elabPrintSig : CommandElab := fun stx =>
208+
withRef stx[0] do
209+
let id := stx[2]
210+
printIdSig id
211+
192212
private def printAxiomsOf (constName : Name) : CommandElabM Unit := do
193213
let axioms ← collectAxioms constName
194214
if axioms.isEmpty then

src/Lean/Parser/Command.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ See also: `#reduce e` for evaluation by term reduction.
499499
"#exit"
500500
@[builtin_command_parser] def print := leading_parser
501501
"#print " >> (ident <|> strLit)
502+
@[builtin_command_parser] def printSig := leading_parser
503+
"#print " >> nonReservedSymbol "sig " >> ident
502504
@[builtin_command_parser] def printAxioms := leading_parser
503505
"#print " >> nonReservedSymbol "axioms " >> ident
504506
@[builtin_command_parser] def printEqns := leading_parser

0 commit comments

Comments
 (0)