lean4-htt/tests/lean/run/mangling.lean
Rob23oba 6bec8adf16
fix: symbol name for native boxed declarations in the interpreter (#12095)
This PR fixes the procedure for finding the mangled symbol name of boxed
variants of native functions. Previously, the wrong symbol name has been
used for names ending in `_`: For example `test_` mangles to `l_test__`
but `test_._boxed` mangles to `l_test___00__boxed`, not
`l_test_____boxed` which the compiler would previously wrongly use.
This probably didn't affect anybody though since the failure condition
is pretty rare: the name of a native function that the interpreter tries
to execute would've had to end in `_`.
2026-01-21 20:38:29 +00:00

94 lines
2.4 KiB
Text

module
import Lean.Compiler.IR.CompilerM
import Lean.Compiler.NameMangling
/-!
# Test behavior of name mangling
-/
open Lean IR ExplicitBoxing
def checkMangle (n : Name) (s : String) : IO Unit := do
if n.mangle "" ≠ s then
throw <| .userError s!"failed: {n} mangles to {n.mangle ""} but expected {s}"
if .demangle s ≠ n then
throw <| .userError s!"failed: {s} demangles to {Lean.Name.demangle s} but expected {n}"
if n ≠ .anonymous ∧ mkMangledBoxedName s ≠ (mkBoxedName n).mangle "" then
throw <| .userError s!"failed: {mkBoxedName n} mangles to {(mkBoxedName n).mangle ""} but \
mkMangledBoxedName produced {mkMangledBoxedName s}"
/-!
Mangling simple identifiers with optional number components and preceding underscores.
-/
#eval checkMangle `ab12 "ab12"
#eval checkMangle ``Lean.Name.mangle "Lean_Name_mangle"
#eval checkMangle `Lean.Name.mangle._aux "Lean_Name_mangle___aux"
#eval checkMangle ((`_private.Lean.Compiler.NameMangling).num 0 ++ `Lean.Name.mangleAux)
"__private_Lean_Compiler_NameMangling_0__Lean_Name_mangleAux"
/-!
Escape sequences in mangled identifiers.
-/
#eval checkMangle `«ÿ» "00_xff"
#eval checkMangle `«α₁» "00_u03b1_u2081"
#eval checkMangle `«𝒫» "00_U0001d4ab"
/-!
Escape sequence disambiguation
-/
#eval checkMangle `a' "a_x27"
#eval checkMangle `a.x27 "a_00x27"
#eval checkMangle `a_' "a___x27"
#eval checkMangle `a._x27 "a_00__x27"
#eval checkMangle `a.u0027 "a_00u0027"
#eval checkMangle `a.U00000027 "a_00U00000027"
#eval checkMangle `a.ucafe "a_00ucafe"
#eval checkMangle `a.uCAFE "a_uCAFE" -- uppercase does not need to be disambiguated
/-!
Trailing underscores in names
-/
#eval checkMangle `a._b "a___b"
#eval checkMangle `a_.b "a___00b"
#eval checkMangle `a_ "a__"
#eval checkMangle `a_.«» "a___00"
#eval checkMangle `a.__ "a_00____"
/-!
Empty name components
-/
#eval checkMangle `a_b "a__b"
#eval checkMangle `a.«».b "a_00_b"
#eval checkMangle `«».b "00_b"
#eval checkMangle `b_.«» "b___00"
/-!
Numbers vs numbers in text
-/
#eval checkMangle ((`a).num 2 ++ `b) "a_2__b"
#eval checkMangle `a.«2_b» "a_002__b"
/-!
Consecutive number components
-/
#eval checkMangle ((`a).num 2 |>.num 3 |>.str "" |>.num 4) "a_2__3__00_4_"
/-!
Preceding number components
-/
#eval checkMangle (.str (.num .anonymous 4) "hi") "4__hi"
/-!
Anonymous vs empty string
-/
#eval checkMangle .anonymous ""
#eval checkMangle `«» "00"
#eval checkMangle `«».«» "00_00"