mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-17 18:34:06 +00:00
This PR replaces three independent name demangling implementations (Lean, C++, Python) with a single source of truth in `Lean.Compiler.NameDemangling`. The new module handles the full pipeline: prefix parsing (`l_`, `lp_`, `_init_`, `initialize_`, `lean_apply_N`, `_lean_main`), postprocessing (suffix flags, private name stripping, hygienic suffix stripping, specialization contexts), backtrace line parsing, and C exports via `@[export]`. The C++ runtime backtrace handler now calls the Lean-exported functions instead of its own 792-line reimplementation. This is safe because `print_backtrace` is only called from `lean_panic_impl` (soft panics), not `lean_internal_panic`. The Python profiler demangler (`script/profiler/lean_demangle.py`) is replaced with a thin subprocess wrapper around a Lean CLI tool, preserving the `demangle_lean_name` API so downstream scripts work unchanged. **New files:** - `src/Lean/Compiler/NameDemangling.lean` — single source of truth (483 lines) - `tests/lean/run/demangling.lean` — comprehensive tests (281 lines) - `script/profiler/lean_demangle_cli.lean` — `c++filt`-style CLI tool **Deleted files:** - `src/runtime/demangle.cpp` (792 lines) - `src/runtime/demangle.h` (26 lines) - `script/profiler/test_demangle.py` (670 lines) Net: −1,381 lines of duplicated C++/Python code. 🤖 Prepared with Claude Code --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
83 lines
2.1 KiB
Python
83 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Lean name demangler — thin wrapper around the Lean CLI tool.
|
|
|
|
Spawns ``lean --run lean_demangle_cli.lean`` as a persistent subprocess
|
|
and communicates via stdin/stdout pipes. This ensures a single source
|
|
of truth for demangling logic (the Lean implementation in
|
|
``Lean.Compiler.NameDemangling``).
|
|
|
|
Usage as a filter (like c++filt):
|
|
echo "l_Lean_Meta_Sym_main" | python lean_demangle.py
|
|
|
|
Usage as a module:
|
|
from lean_demangle import demangle_lean_name
|
|
print(demangle_lean_name("l_Lean_Meta_Sym_main"))
|
|
"""
|
|
|
|
import atexit
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
_process = None
|
|
_script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
_cli_script = os.path.join(_script_dir, "lean_demangle_cli.lean")
|
|
|
|
|
|
def _get_process():
|
|
"""Get or create the persistent Lean demangler subprocess."""
|
|
global _process
|
|
if _process is not None and _process.poll() is None:
|
|
return _process
|
|
|
|
lean = os.environ.get("LEAN", "lean")
|
|
_process = subprocess.Popen(
|
|
[lean, "--run", _cli_script],
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.DEVNULL,
|
|
text=True,
|
|
bufsize=1, # line buffered
|
|
)
|
|
atexit.register(_cleanup)
|
|
return _process
|
|
|
|
|
|
def _cleanup():
|
|
global _process
|
|
if _process is not None:
|
|
try:
|
|
_process.stdin.close()
|
|
_process.wait(timeout=5)
|
|
except Exception:
|
|
_process.kill()
|
|
_process = None
|
|
|
|
|
|
def demangle_lean_name(mangled):
|
|
"""
|
|
Demangle a C symbol name produced by the Lean 4 compiler.
|
|
|
|
Returns a human-friendly demangled name, or the original string
|
|
if it is not a Lean symbol.
|
|
"""
|
|
try:
|
|
proc = _get_process()
|
|
proc.stdin.write(mangled + "\n")
|
|
proc.stdin.flush()
|
|
result = proc.stdout.readline().rstrip("\n")
|
|
return result if result else mangled
|
|
except Exception:
|
|
return mangled
|
|
|
|
|
|
def main():
|
|
"""Filter stdin, demangling Lean names."""
|
|
for line in sys.stdin:
|
|
print(demangle_lean_name(line.rstrip("\n")))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|