Skip to content
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
4e002c9
feat: delabSubscript and delabSuperscript
gio256 Mar 17, 2025
66eb431
fix: private function application
gio256 Mar 17, 2025
f5a8774
test: restructure sub/superscript delab tests
gio256 Mar 17, 2025
d561fd0
fix: subscript partially-applied functions
gio256 Mar 17, 2025
b5ae8b9
test: better syntax for subscript test macro
gio256 Mar 17, 2025
a019c11
fix: prefer getExpr to passing around expression
gio256 Mar 17, 2025
315b848
fix: () : Unit is valid in subscripts
gio256 Mar 17, 2025
708ce39
fix: camelCase defs
gio256 Mar 17, 2025
36e3612
test: test partially-applied fn in subscript
gio256 Mar 17, 2025
04edce2
chore: make sub/superscriptable fns private
gio256 Mar 17, 2025
2355936
doc: clean up and comment
gio256 Mar 18, 2025
3fdd2b1
chore: clarify name function
gio256 Mar 18, 2025
00a22e5
doc: clarify comment
gio256 Mar 18, 2025
abc6974
chore: imports, comments, add delab section
gio256 Mar 18, 2025
9b548f3
test: add tests that don't trigger the delaborator
gio256 Mar 18, 2025
2e571a2
fix: delab first, then check subscript validity
gio256 Mar 18, 2025
a870c10
chore: clean up isSuperscriptable
gio256 Mar 18, 2025
ad05d28
chore: combine superscriptable and subscriptable
gio256 Mar 18, 2025
adc446e
test: rm smul test
gio256 Mar 18, 2025
5a5abad
doc: add comment for Superscript.isValid
gio256 Mar 18, 2025
1dfdd75
test: clean up test fn naming
gio256 Mar 18, 2025
eab471f
test: add nested superscript(subscript) tests
gio256 Mar 18, 2025
ec0c3ad
doc: fix typo
gio256 Mar 19, 2025
4b97140
test: add dot notation tests
gio256 Mar 19, 2025
272b535
chore: rm unused universe
gio256 Mar 19, 2025
fbf9915
style: use anon dot notation in delabSubscript fns
gio256 Mar 19, 2025
df5fd0c
fix: reject values that are already subscripted
gio256 Mar 19, 2025
c93827e
Merge branch 'master' into gio/subscript
gio256 Mar 19, 2025
8bb34e3
chore: clarify Superscript.isValid logic
gio256 Mar 19, 2025
e78cd37
style: golf Superscript.isValid valid helper fn
gio256 Apr 17, 2025
2f65a68
style: golf Superscript.isValid scripted helper fn
gio256 Apr 17, 2025
26e7384
restore using decl_name to guarantee SyntaxNodeKind uniqueness
kmill May 1, 2025
fb95ea2
minimize diff
kmill May 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion Mathlib/Util/Superscript.lean
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ universe u

namespace Mathlib.Tactic

open Lean Parser PrettyPrinter Std
open Lean Parser PrettyPrinter Delaborator Std

namespace Superscript

Expand Down Expand Up @@ -225,6 +225,30 @@ def scriptParser.formatter (name : String) (m : Mapping) (k : SyntaxNodeKind) (p
| .ok newStack =>
set { st with stack := stack ++ newStack }

section Delab

/-- Returns `true` if every character in `s` can be subscripted. -/
private def isSubscriptable (s : String) : Bool :=
s.toList.all fun x ↦ x == ' ' || Mapping.subscript.toSpecial.contains x

/-- Returns `true` if every character in `s` can be superscripted. -/
private def isSuperscriptable (s : String) : Bool :=
s.toList.all fun x ↦ x == ' ' || Mapping.superscript.toSpecial.contains x

private partial def superscriptable : Syntax → DelabM Unit
| .node _ _ args => args.forM superscriptable
| .atom _ val => guard <| isSuperscriptable val
| .ident _ _ val _ => guard <| isSuperscriptable val.toString
| _ => failure

private partial def subscriptable : Syntax → DelabM Unit
| .node _ _ args => args.forM subscriptable
| .atom _ s => guard <| isSubscriptable s
| .ident _ _ s _ => guard <| isSubscriptable s.toString
| _ => failure

end Delab

end Superscript

/--
Expand Down Expand Up @@ -263,6 +287,17 @@ def superscriptTerm := leading_parser (withAnonymousAntiquot := false) superscri

initialize register_parser_alias superscript

/-- Checks that the current expression can be superscripted before delaborating.

This is a conservative approximation — it may not succeed even given a valid
superscriptable expression as input.

See `Mapping.superscript` in this file for legal superscript characters. -/
def delabSuperscript : Delab := do
let de ← delab
let _ ← Superscript.superscriptable de.raw
pure de

/--
The parser `subscript(term)` parses a subscript. Basic usage is:
```
Expand Down Expand Up @@ -299,4 +334,15 @@ def subscriptTerm := leading_parser (withAnonymousAntiquot := false) subscript t

initialize register_parser_alias subscript

/-- Checks that the current expression can be subscripted before delaborating.

This is a conservative approximation — it may not succeed even given a valid
subscriptable expression as input.

See `Mapping.subscript` in this file for legal subscript characters. -/
def delabSubscript : Delab := do
let de ← delab
let _ ← Superscript.subscriptable de.raw
pure de

end Mathlib.Tactic
147 changes: 147 additions & 0 deletions MathlibTest/superscript.lean
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,150 @@ run_cmd Lean.Elab.Command.liftTermElabM do
Lean.logInfo <| ← Lean.PrettyPrinter.ppTerm <| ← `(term| ($a)$α:subscript)

end

section delab

open Lean PrettyPrinter.Delaborator SubExpr
open Mathlib.Tactic (delabSubscript delabSuperscript)

private def check_subscript {α : Type} (_ : α) := ()
local syntax:arg "test(" noWs subscript(term) noWs ")" : term
local macro_rules | `(test($a:subscript)) => `(check_subscript $a)

private def check_superscript {α : Type} (_ : α) := ()
local syntax:arg "test(" noWs superscript(term) noWs ")" : term
local macro_rules | `(test($a:superscript)) => `(check_superscript $a)

@[app_delab check_subscript]
private def delabCheckSubscript : Delab := withOverApp 2 do
let sub ← withAppArg delabSubscript
`(test($sub:subscript))

@[app_delab check_superscript]
private def delabCheckSuperscript : Delab := withOverApp 2 do
let sup ← withAppArg delabSuperscript
`(test($sup:superscript))

universe u v w

/-- `α` can not be subscripted or superscripted. -/
private def α {γ : Type u} {δ : Type v} : γ → δ → δ := fun _ ↦ id
/-- `β` can be both subscripted and superscripted. -/
private def β {γ : Type u} {δ : Type v} : γ → δ → δ := fun _ ↦ id

/-- `d` can not be subscripted, so we create an alias for `id`. -/
private abbrev ID {γ : Sort u} := @id γ

variable (n : String)

section subscript

/-- info: test(₁₂₃₄₅₆₇₈₉₀ ₌₌ ₁₂₃₄₅₆₇₈₉₀) : Unit -/
#guard_msgs in #check test(₁₂₃₄₅₆₇₈₉₀ ₌₌ ₁₂₃₄₅₆₇₈₉₀)
/-- info: test(ᵦ ₙ ₍₁ ₊ ₂ ₋ ₃ ₌ ₀₎) : Unit -/
#guard_msgs in #check test(ᵦ ₙ ₍₁ ₊ ₂ ₋ ₃ ₌ ₀₎)
/-- info: test(ᵦ) : Unit -/
#guard_msgs in #check test(ᵦ)
/-- info: test(ᵦ ₍₎) : Unit -/
#guard_msgs in #check test(ᵦ ₍₎)
/-- info: test(ᵦ ᵦ ᵦ ᵦ) : Unit -/
#guard_msgs in #check test(ᵦ ᵦ ᵦ ᵦ)
/-- info: test(ɪᴅ ɪᴅ ₃₇) : Unit -/
#guard_msgs in #check test(ɪᴅ ɪᴅ ₃₇)

end subscript

section superscript

/-- info: test(¹²³⁴⁵⁶⁷⁸⁹⁰ ⁼⁼ ¹²³⁴⁵⁶⁷⁸⁹⁰) : Unit -/
#guard_msgs in #check test(¹²³⁴⁵⁶⁷⁸⁹⁰ ⁼⁼ ¹²³⁴⁵⁶⁷⁸⁹⁰)
/-- info: test(ᵝ ⁿ ⁽¹ ⁺ ² ⁻ ³ ⁼ ⁰⁾) : Unit -/
#guard_msgs in #check test(ᵝ ⁿ ⁽¹ ⁺ ² ⁻ ³ ⁼ ⁰⁾)
/-- info: test(ᵝ) : Unit -/
#guard_msgs in #check test(ᵝ)
/-- info: test(ᵝ ⁽⁾) : Unit -/
#guard_msgs in #check test(ᵝ ⁽⁾)
/-- info: test(ᵝ ᵝ ᵝ ᵝ) : Unit -/
#guard_msgs in #check test(ᵝ ᵝ ᵝ ᵝ)
/-- info: test(ⁱᵈ ⁱᵈ ³⁷) : Unit -/
#guard_msgs in #check test(ⁱᵈ ⁱᵈ ³⁷)

end superscript

variable (x_x : String)

private def card {γ : Sort u} := @id γ
local prefix:arg "#" => card

private def factorial {γ : Sort u} := @id γ
local notation:10000 n "!" => factorial n

private class HSMul (α : Type u) (β : Type v) (γ : outParam (Type w)) where
hSMul : α → β → γ
instance : HSMul Nat Nat Nat where
hSMul a b := a * b
infixr:73 " • " => HSMul.hSMul

section no_subscript

/-- info: check_subscript x_x : Unit -/
#guard_msgs in #check check_subscript x_x
/-- info: check_subscript (α 0 0) : Unit -/
#guard_msgs in #check check_subscript (α 0 0)
/-- info: check_subscript (0 * 1) : Unit -/
#guard_msgs in #check check_subscript (0 * 1)
/-- info: check_subscript (0 ^ 1) : Unit -/
#guard_msgs in #check check_subscript (0 ^ 1)
/-- info: check_subscript [1] : Unit -/
#guard_msgs in #check check_subscript [1]
/-- info: check_subscript #n : Unit -/
#guard_msgs in #check check_subscript #n
/-- info: check_subscript 2! : Unit -/
#guard_msgs in #check check_subscript 2!
/-- info: check_subscript (1 • 2) : Unit -/
#guard_msgs in #check check_subscript (1 • 2)

set_option pp.mvars false in
/-- info: check_subscript ?_ : Unit -/
#guard_msgs in #check check_subscript ?_

/- The delaborator should fail because `n` is shadowed and `✝` can not be
subscripted. -/
variable {x} (hx : x = test(ₙ)) (n : True) in
/-- info: hx : x = check_subscript n✝ -/
#guard_msgs in #check hx

end no_subscript

section no_superscript

/-- info: check_superscript x_x : Unit -/
#guard_msgs in #check check_superscript x_x
/-- info: check_superscript (α 0 0) : Unit -/
#guard_msgs in #check check_superscript (α 0 0)
/-- info: check_superscript (0 * 1) : Unit -/
#guard_msgs in #check check_superscript (0 * 1)
/-- info: check_superscript (0 ^ 1) : Unit -/
#guard_msgs in #check check_superscript (0 ^ 1)
/-- info: check_superscript [1] : Unit -/
#guard_msgs in #check check_superscript [1]
/-- info: check_superscript #n : Unit -/
#guard_msgs in #check check_superscript #n
/-- info: check_superscript 2! : Unit -/
#guard_msgs in #check check_superscript 2!
/-- info: check_superscript (1 • 2) : Unit -/
#guard_msgs in #check check_superscript (1 • 2)

set_option pp.mvars false in
/-- info: check_superscript ?_ : Unit -/
#guard_msgs in #check check_superscript ?_

/- The delaborator should fail because `n` is shadowed and `✝` can not be
superscripted. -/
variable {x} (hx : x = test(ⁿ)) (n : True) in
/-- info: hx : x = check_superscript n✝ -/
#guard_msgs in #check hx

end no_superscript

end delab