demangle 0.5.2__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. {demangle-0.5.2 → demangle-0.6.0}/.gitignore +3 -0
  2. {demangle-0.5.2 → demangle-0.6.0}/CHANGELOG.md +28 -1
  3. {demangle-0.5.2 → demangle-0.6.0}/CITATION.cff +1 -1
  4. {demangle-0.5.2 → demangle-0.6.0}/CONTRIBUTING.md +16 -1
  5. {demangle-0.5.2 → demangle-0.6.0}/PKG-INFO +8 -2
  6. {demangle-0.5.2 → demangle-0.6.0}/README.md +7 -1
  7. {demangle-0.5.2 → demangle-0.6.0}/SECURITY.md +2 -2
  8. demangle-0.6.0/benchmarks/baseline.json +68 -0
  9. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/bench.py +79 -8
  10. demangle-0.6.0/docs/hooks.py +80 -0
  11. demangle-0.6.0/docs/playground.md +34 -0
  12. {demangle-0.5.2 → demangle-0.6.0}/docs/reference/core.md +1 -0
  13. {demangle-0.5.2 → demangle-0.6.0}/docs/reference/schemes.md +1 -0
  14. {demangle-0.5.2 → demangle-0.6.0}/mkdocs.yml +4 -0
  15. demangle-0.6.0/playground/README.md +48 -0
  16. demangle-0.6.0/playground/index.html +275 -0
  17. demangle-0.6.0/playground/playground-worker.js +48 -0
  18. demangle-0.6.0/playground/playground.js +622 -0
  19. demangle-0.6.0/playground/playground_bridge.py +112 -0
  20. demangle-0.6.0/playground/style.css +932 -0
  21. {demangle-0.5.2 → demangle-0.6.0}/pyproject.toml +8 -0
  22. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/__init__.py +1 -1
  23. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/cache.py +2 -0
  24. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/decorations.py +7 -1
  25. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/errors.py +10 -0
  26. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/limits.py +2 -0
  27. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/plugin.py +2 -0
  28. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/reader.py +8 -0
  29. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/registry.py +13 -0
  30. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/spelling.py +10 -0
  31. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/style.py +8 -0
  32. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/itanium/options.py +2 -0
  33. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/msvc/__init__.py +3 -1
  34. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/msvc/_parser.py +24 -2
  35. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/msvc/nodes.py +35 -6
  36. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/rust/__init__.py +11 -1
  37. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/_printer.py +5 -2
  38. demangle-0.6.0/tests/browser/test_playground_browser.py +437 -0
  39. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/swift-upstream.txt +1 -1
  40. {demangle-0.5.2 → demangle-0.6.0}/tests/test_benchmarks.py +16 -0
  41. {demangle-0.5.2 → demangle-0.6.0}/tests/test_msvc.py +96 -1
  42. demangle-0.6.0/tests/test_playground.py +173 -0
  43. {demangle-0.5.2 → demangle-0.6.0}/tests/test_swift.py +42 -0
  44. {demangle-0.5.2 → demangle-0.6.0}/tools/enumerate.py +8 -0
  45. {demangle-0.5.2 → demangle-0.6.0}/tools/upstream_drift.py +5 -1
  46. demangle-0.5.2/benchmarks/baseline.json +0 -38
  47. {demangle-0.5.2 → demangle-0.6.0}/ARCHITECTURE.md +0 -0
  48. {demangle-0.5.2 → demangle-0.6.0}/CODE_OF_CONDUCT.md +0 -0
  49. {demangle-0.5.2 → demangle-0.6.0}/CONFORMANCE.md +0 -0
  50. {demangle-0.5.2 → demangle-0.6.0}/LICENSE +0 -0
  51. {demangle-0.5.2 → demangle-0.6.0}/NOTICE +0 -0
  52. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_api.py +0 -0
  53. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_api_results.json +0 -0
  54. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_ast_optimization_results.json +0 -0
  55. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_cli_results.json +0 -0
  56. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_core.py +0 -0
  57. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_followup_results.json +0 -0
  58. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_graph.py +0 -0
  59. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_integrated_results.json +0 -0
  60. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_jni.py +0 -0
  61. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_nim.py +0 -0
  62. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_nim_optimization_results.json +0 -0
  63. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_objc.py +0 -0
  64. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_results.json +0 -0
  65. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_rust.py +0 -0
  66. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_rust_optimization_results.json +0 -0
  67. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_stream.py +0 -0
  68. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_swift.py +0 -0
  69. {demangle-0.5.2 → demangle-0.6.0}/benchmarks/audit_swift_unicode_results.json +0 -0
  70. {demangle-0.5.2 → demangle-0.6.0}/docs/ARCHITECTURE.md +0 -0
  71. {demangle-0.5.2 → demangle-0.6.0}/docs/CHANGELOG.md +0 -0
  72. {demangle-0.5.2 → demangle-0.6.0}/docs/CONFORMANCE.md +0 -0
  73. {demangle-0.5.2 → demangle-0.6.0}/docs/CONTRIBUTING.md +0 -0
  74. {demangle-0.5.2 → demangle-0.6.0}/docs/SECURITY.md +0 -0
  75. {demangle-0.5.2 → demangle-0.6.0}/docs/adding-a-scheme.md +0 -0
  76. {demangle-0.5.2 → demangle-0.6.0}/docs/analysing-a-binary.md +0 -0
  77. {demangle-0.5.2 → demangle-0.6.0}/docs/index.md +0 -0
  78. {demangle-0.5.2 → demangle-0.6.0}/docs/labelling-a-symbol-table.md +0 -0
  79. {demangle-0.5.2 → demangle-0.6.0}/docs/reference/api.md +0 -0
  80. {demangle-0.5.2 → demangle-0.6.0}/docs/specs/itanium-grammar.txt +0 -0
  81. {demangle-0.5.2 → demangle-0.6.0}/docs/testing.md +0 -0
  82. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/__main__.py +0 -0
  83. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/_signature.py +0 -0
  84. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/api.py +0 -0
  85. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/cli.py +0 -0
  86. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/__init__.py +0 -0
  87. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/ast.py +0 -0
  88. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/core/builder.py +0 -0
  89. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/filter.py +0 -0
  90. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/py.typed +0 -0
  91. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/__init__.py +0 -0
  92. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/ada/__init__.py +0 -0
  93. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/ada/_parser.py +0 -0
  94. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/ada/nodes.py +0 -0
  95. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/codewarrior/__init__.py +0 -0
  96. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/codewarrior/_parser.py +0 -0
  97. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/codewarrior/nodes.py +0 -0
  98. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/codewarrior/options.py +0 -0
  99. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/d/__init__.py +0 -0
  100. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/d/_parser.py +0 -0
  101. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/d/nodes.py +0 -0
  102. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/delphi/__init__.py +0 -0
  103. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/delphi/_parser.py +0 -0
  104. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/delphi/nodes.py +0 -0
  105. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/gnuv2/__init__.py +0 -0
  106. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/gnuv2/_parser.py +0 -0
  107. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/gnuv2/nodes.py +0 -0
  108. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/gnuv2/options.py +0 -0
  109. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/go/__init__.py +0 -0
  110. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/go/_parser.py +0 -0
  111. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/go/nodes.py +0 -0
  112. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/itanium/__init__.py +0 -0
  113. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/itanium/parser.py +0 -0
  114. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/itanium/substitutions.py +0 -0
  115. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/itanium/tables.py +0 -0
  116. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/jni/__init__.py +0 -0
  117. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/jni/_parser.py +0 -0
  118. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/jni/nodes.py +0 -0
  119. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/msvc/options.py +0 -0
  120. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/nim/__init__.py +0 -0
  121. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/nim/_parser.py +0 -0
  122. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/nim/nodes.py +0 -0
  123. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/objc/__init__.py +0 -0
  124. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/objc/_parser.py +0 -0
  125. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/objc/nodes.py +0 -0
  126. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/pascal/__init__.py +0 -0
  127. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/pascal/_parser.py +0 -0
  128. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/pascal/nodes.py +0 -0
  129. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/rust/_dispatch.py +0 -0
  130. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/rust/_legacy.py +0 -0
  131. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/rust/_v0.py +0 -0
  132. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/rust/nodes.py +0 -0
  133. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/rust/options.py +0 -0
  134. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/__init__.py +0 -0
  135. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/_demangler.py +0 -0
  136. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/_node.py +0 -0
  137. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/_old_demangler.py +0 -0
  138. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/_punycode.py +0 -0
  139. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/nodes.py +0 -0
  140. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/options.py +0 -0
  141. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/resolve.py +0 -0
  142. {demangle-0.5.2 → demangle-0.6.0}/src/demangle/schemes/swift/symbolic.py +0 -0
  143. {demangle-0.5.2 → demangle-0.6.0}/tests/__init__.py +0 -0
  144. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/ada-libiberty.txt +0 -0
  145. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/ada-real-world.txt +0 -0
  146. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/codewarrior-cwdemangle.txt +0 -0
  147. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/d-libiberty.txt +0 -0
  148. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/d-real-world.txt +0 -0
  149. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/delphi-constructs.txt +0 -0
  150. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/delphi-real-world.txt +0 -0
  151. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/delphi-refusals.txt +0 -0
  152. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/delphi-tdump.txt +0 -0
  153. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/gnuv2-libiberty.txt +0 -0
  154. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/gnuv2-real-world.txt +0 -0
  155. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/go-real-world.txt +0 -0
  156. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-libcxxabi.txt.gz +0 -0
  157. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-libstdcxx.txt +0 -0
  158. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-real-world-gnu.txt +0 -0
  159. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-real-world.txt +0 -0
  160. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-reference-defects.txt +0 -0
  161. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-types-llvm.txt +0 -0
  162. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/itanium-types.txt +0 -0
  163. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/jni-real-world.txt +0 -0
  164. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-arm64ec.txt +0 -0
  165. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-boost.txt +0 -0
  166. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-clang.txt +0 -0
  167. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-dbghelp.txt +0 -0
  168. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-llvm-corpus.txt +0 -0
  169. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-name-only.txt +0 -0
  170. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-reference-defects.txt +0 -0
  171. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-suppressions.txt +0 -0
  172. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/msvc-type-descriptors.txt +0 -0
  173. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/nim-lossy.txt +0 -0
  174. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/nim-real-world.txt +0 -0
  175. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/objc-lossy.txt +0 -0
  176. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/objc-real-world.txt +0 -0
  177. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/objc-refusals.txt +0 -0
  178. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/pascal-real-world.txt +0 -0
  179. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/pascal-refusals.txt +0 -0
  180. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/reported/d-gnu.txt +0 -0
  181. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/reported/gnuv2-gnu.txt +0 -0
  182. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/reported/itanium-gnu.txt +0 -0
  183. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/reported/itanium.txt +0 -0
  184. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/reported/rust.txt +0 -0
  185. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/reported/swift.txt +0 -0
  186. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/rust-real-world.txt +0 -0
  187. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/rust-toolchain.txt +0 -0
  188. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/rustc-upstream.txt +0 -0
  189. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/swift-real-world.txt +0 -0
  190. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/swift-reference-defects.txt +0 -0
  191. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/swift-refusals.txt +0 -0
  192. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/swift-simplified.txt +0 -0
  193. {demangle-0.5.2 → demangle-0.6.0}/tests/conformance/swift-symbolic.txt +0 -0
  194. {demangle-0.5.2 → demangle-0.6.0}/tests/conftest.py +0 -0
  195. {demangle-0.5.2 → demangle-0.6.0}/tests/test_ada.py +0 -0
  196. {demangle-0.5.2 → demangle-0.6.0}/tests/test_address_of.py +0 -0
  197. {demangle-0.5.2 → demangle-0.6.0}/tests/test_api.py +0 -0
  198. {demangle-0.5.2 → demangle-0.6.0}/tests/test_api_surface.py +0 -0
  199. {demangle-0.5.2 → demangle-0.6.0}/tests/test_architecture.py +0 -0
  200. {demangle-0.5.2 → demangle-0.6.0}/tests/test_cli.py +0 -0
  201. {demangle-0.5.2 → demangle-0.6.0}/tests/test_codewarrior.py +0 -0
  202. {demangle-0.5.2 → demangle-0.6.0}/tests/test_concurrency.py +0 -0
  203. {demangle-0.5.2 → demangle-0.6.0}/tests/test_conformance.py +0 -0
  204. {demangle-0.5.2 → demangle-0.6.0}/tests/test_core.py +0 -0
  205. {demangle-0.5.2 → demangle-0.6.0}/tests/test_d.py +0 -0
  206. {demangle-0.5.2 → demangle-0.6.0}/tests/test_delphi.py +0 -0
  207. {demangle-0.5.2 → demangle-0.6.0}/tests/test_differential.py +0 -0
  208. {demangle-0.5.2 → demangle-0.6.0}/tests/test_docs.py +0 -0
  209. {demangle-0.5.2 → demangle-0.6.0}/tests/test_expressions.py +0 -0
  210. {demangle-0.5.2 → demangle-0.6.0}/tests/test_gnu_expressions.py +0 -0
  211. {demangle-0.5.2 → demangle-0.6.0}/tests/test_gnuv2.py +0 -0
  212. {demangle-0.5.2 → demangle-0.6.0}/tests/test_go.py +0 -0
  213. {demangle-0.5.2 → demangle-0.6.0}/tests/test_invariants.py +0 -0
  214. {demangle-0.5.2 → demangle-0.6.0}/tests/test_itanium_apple_auto.py +0 -0
  215. {demangle-0.5.2 → demangle-0.6.0}/tests/test_itanium_closure_prefix.py +0 -0
  216. {demangle-0.5.2 → demangle-0.6.0}/tests/test_itanium_import_thunk.py +0 -0
  217. {demangle-0.5.2 → demangle-0.6.0}/tests/test_itanium_utf8.py +0 -0
  218. {demangle-0.5.2 → demangle-0.6.0}/tests/test_jni.py +0 -0
  219. {demangle-0.5.2 → demangle-0.6.0}/tests/test_limits.py +0 -0
  220. {demangle-0.5.2 → demangle-0.6.0}/tests/test_local_names.py +0 -0
  221. {demangle-0.5.2 → demangle-0.6.0}/tests/test_msvc_arm64ec.py +0 -0
  222. {demangle-0.5.2 → demangle-0.6.0}/tests/test_msvc_ast.py +0 -0
  223. {demangle-0.5.2 → demangle-0.6.0}/tests/test_msvc_descriptors.py +0 -0
  224. {demangle-0.5.2 → demangle-0.6.0}/tests/test_msvc_options.py +0 -0
  225. {demangle-0.5.2 → demangle-0.6.0}/tests/test_nim.py +0 -0
  226. {demangle-0.5.2 → demangle-0.6.0}/tests/test_objc.py +0 -0
  227. {demangle-0.5.2 → demangle-0.6.0}/tests/test_parity.py +0 -0
  228. {demangle-0.5.2 → demangle-0.6.0}/tests/test_pascal.py +0 -0
  229. {demangle-0.5.2 → demangle-0.6.0}/tests/test_readme.py +0 -0
  230. {demangle-0.5.2 → demangle-0.6.0}/tests/test_repro.py +0 -0
  231. {demangle-0.5.2 → demangle-0.6.0}/tests/test_robustness.py +0 -0
  232. {demangle-0.5.2 → demangle-0.6.0}/tests/test_rust.py +0 -0
  233. {demangle-0.5.2 → demangle-0.6.0}/tests/test_rust_ast.py +0 -0
  234. {demangle-0.5.2 → demangle-0.6.0}/tests/test_rust_consts.py +0 -0
  235. {demangle-0.5.2 → demangle-0.6.0}/tests/test_signature.py +0 -0
  236. {demangle-0.5.2 → demangle-0.6.0}/tests/test_special_names.py +0 -0
  237. {demangle-0.5.2 → demangle-0.6.0}/tests/test_substitution_parameters.py +0 -0
  238. {demangle-0.5.2 → demangle-0.6.0}/tests/test_swift_simplified.py +0 -0
  239. {demangle-0.5.2 → demangle-0.6.0}/tests/test_swift_symbolic.py +0 -0
  240. {demangle-0.5.2 → demangle-0.6.0}/tests/test_types.py +0 -0
  241. {demangle-0.5.2 → demangle-0.6.0}/tests/test_upstream_drift.py +0 -0
  242. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/features.cpp +0 -0
  243. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/go/go.mod +0 -0
  244. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/go/main.go +0 -0
  245. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/go/plain/lib.go +0 -0
  246. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/go/v2.5/lib.go +0 -0
  247. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/go/weird.pkg.name/lib.go +0 -0
  248. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/modern.cpp +0 -0
  249. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/modern23.cpp +0 -0
  250. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/msvc/modern.cpp +0 -0
  251. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/msvc/msvc.cpp +0 -0
  252. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/README.md +0 -0
  253. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/auto_marshall.cpp +0 -0
  254. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/closure_prefix.cpp +0 -0
  255. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/division.cpp +0 -0
  256. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/generic_lambda.cpp +0 -0
  257. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/inheriting_constructor.cpp +0 -0
  258. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/insort.cpp +0 -0
  259. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/insort_composite.cpp +0 -0
  260. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/member_template_lambda.cpp +0 -0
  261. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/prepare_execution.cpp +0 -0
  262. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/template_template_param.cpp +0 -0
  263. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/reference_defects/value_init_new.cpp +0 -0
  264. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/rust/consts.rs +0 -0
  265. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/rust/features.rs +0 -0
  266. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/rust/library.rs +0 -0
  267. {demangle-0.5.2 → demangle-0.6.0}/tools/corpus_sources/rust/types.rs +0 -0
  268. {demangle-0.5.2 → demangle-0.6.0}/tools/cplus-dem-reference/README.md +0 -0
  269. {demangle-0.5.2 → demangle-0.6.0}/tools/cplus-dem-reference/SHA256SUMS +0 -0
  270. {demangle-0.5.2 → demangle-0.6.0}/tools/cplus-dem-reference/build.sh +0 -0
  271. {demangle-0.5.2 → demangle-0.6.0}/tools/cplus-dem-reference/main.c +0 -0
  272. {demangle-0.5.2 → demangle-0.6.0}/tools/differential.py +0 -0
  273. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_ada_corpus.py +0 -0
  274. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_corpus.py +0 -0
  275. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_d_corpus.py +0 -0
  276. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_delphi_corpus.py +0 -0
  277. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_go_corpus.py +0 -0
  278. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_msvc_dbghelp_corpus.py +0 -0
  279. {demangle-0.5.2 → demangle-0.6.0}/tools/generate_rust_corpus.py +0 -0
  280. {demangle-0.5.2 → demangle-0.6.0}/tools/invariants.py +0 -0
  281. {demangle-0.5.2 → demangle-0.6.0}/tools/mutate.py +0 -0
  282. {demangle-0.5.2 → demangle-0.6.0}/tools/probe_substitutions.py +0 -0
  283. {demangle-0.5.2 → demangle-0.6.0}/tools/repro.py +0 -0
  284. {demangle-0.5.2 → demangle-0.6.0}/tools/rustc-demangle-reference/Cargo.lock +0 -0
  285. {demangle-0.5.2 → demangle-0.6.0}/tools/rustc-demangle-reference/Cargo.toml +0 -0
  286. {demangle-0.5.2 → demangle-0.6.0}/tools/rustc-demangle-reference/README.md +0 -0
  287. {demangle-0.5.2 → demangle-0.6.0}/tools/rustc-demangle-reference/src/main.rs +0 -0
  288. {demangle-0.5.2 → demangle-0.6.0}/tools/sweep_rust_chars.py +0 -0
  289. {demangle-0.5.2 → demangle-0.6.0}/tools/swift-demangle-reference/README.md +0 -0
  290. {demangle-0.5.2 → demangle-0.6.0}/tools/swift-demangle-reference/build.sh +0 -0
  291. {demangle-0.5.2 → demangle-0.6.0}/tools/swift-demangle-reference/main.cpp +0 -0
@@ -19,3 +19,6 @@ tools/swift-demangle-reference/swift/
19
19
  tools/swift-demangle-reference/build/
20
20
  tools/cplus-dem-reference/gcc/
21
21
  tools/cplus-dem-reference/build/
22
+ .agents/
23
+ docs/assets/demangle.zip
24
+ playground/assets/
@@ -8,6 +8,32 @@ the reference demanglers, and a **Performance** section.
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.6.0] - 2026-10-11
12
+
13
+ ### Fixed
14
+
15
+ - Preserve playground input and selected settings while its runtime loads. Scheme
16
+ selectors and output controls stay inside their columns on narrow screens and with
17
+ enlarged text. AST references reveal collapsed ancestors and support keyboard use.
18
+
19
+ ### Added
20
+
21
+ - MSVC C++20 three-way comparison (`operator<=>`) and ARM64e pointer authentication
22
+ qualifiers, including their structured AST representation.
23
+ - Swift inverse conformance to `~Deinitable`, with module-name display options respected.
24
+ - A standalone browser playground with theme switching and keyboard shortcuts.
25
+ - Shareable playground links and the loaded library version, runtime retry controls,
26
+ and browser regression tests including a real Pyodide smoke test in CI.
27
+ - Bounded Swift and cross-scheme signature benchmarks with successful-work checks.
28
+
29
+ ### Performance
30
+
31
+ - Run playground parsing in a worker and derive signature and AST data from one parse.
32
+ Output view changes reuse the result; AST expansion is lazy and paged with a display
33
+ budget while raw JSON remains complete.
34
+ - Deliver a deterministic, zipimportable source archive instead of a synthetic wheel
35
+ and duplicate base64 bundle.
36
+
11
37
  ## [0.5.2] - 2026-10-10
12
38
 
13
39
  ### Fixed
@@ -4037,7 +4063,8 @@ substitution table contents, pinned by name.
4037
4063
  faster by doing less work.
4038
4064
  - API reference published from docstrings at <https://r0ny123.github.io/demangle/>.
4039
4065
 
4040
- [Unreleased]: https://github.com/r0ny123/demangle/compare/v0.5.2...HEAD
4066
+ [Unreleased]: https://github.com/r0ny123/demangle/compare/v0.6.0...HEAD
4067
+ [0.6.0]: https://github.com/r0ny123/demangle/compare/v0.5.2...v0.6.0
4041
4068
  [0.5.2]: https://github.com/r0ny123/demangle/compare/v0.5.1...v0.5.2
4042
4069
  [0.5.1]: https://github.com/r0ny123/demangle/compare/v0.5.0...v0.5.1
4043
4070
  [0.5.0]: https://github.com/r0ny123/demangle/compare/v0.4.0...v0.5.0
@@ -5,4 +5,4 @@ authors:
5
5
  - name: demangle contributors
6
6
  license: MIT
7
7
  repository-code: "https://github.com/r0ny123/demangle"
8
- version: "0.5.2"
8
+ version: "0.6.0"
@@ -40,7 +40,22 @@ Development requirements are [dependency groups](https://peps.python.org/pep-073
40
40
  not extras. An extra is a *published* feature of the distribution -- `pip install
41
41
  demangle[dev]` would appear on PyPI as something users are invited to install -- and a
42
42
  linter is not a feature of a demangler. The groups are `test`, `format`, `lint`, `docs`,
43
- and `dev`, which includes the first three.
43
+ `browser`, and `dev`, which includes the first three.
44
+
45
+ The browser suite is opt-in: it needs the browser dependency group, a built docs site,
46
+ and Chromium. It uses a deterministic fake worker for UI regressions; the real Pyodide
47
+ CDN smoke test is separately opt-in.
48
+
49
+ ```console
50
+ uv pip install -e . --group browser --group docs --group test
51
+ python -m playwright install chromium
52
+ mkdocs build --strict
53
+ DEMANGLE_BROWSER_TESTS=1 python -m pytest -q tests/browser/test_playground_browser.py
54
+
55
+ # Also exercise Pyodide from its CDN, as the browser CI job does.
56
+ DEMANGLE_BROWSER_TESTS=1 DEMANGLE_PYODIDE_SMOKE=1 \
57
+ python -m pytest -q tests/browser/test_playground_browser.py
58
+ ```
44
59
 
45
60
  The toolchain is deliberately the fast one: **ruff** for linting and formatting (it
46
61
  replaces black, isort, flake8 and pyupgrade), **ty** for type checking (it replaces
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: demangle
3
- Version: 0.5.2
3
+ Version: 0.6.0
4
4
  Summary: Read mangled symbol names -- Itanium C++, MSVC, Rust, Swift, Objective-C, Go, D, Nim, Free Pascal, Delphi, Ada/GNAT, JNI and pre-Itanium C++ (g++ 2.x, cfront/ARM, Lucid, HP aCC, CodeWarrior) -- in pure Python, with no dependencies.
5
5
  Project-URL: Homepage, https://github.com/r0ny123/demangle
6
6
  Project-URL: Documentation, https://r0ny123.github.io/demangle/
@@ -37,6 +37,7 @@ Description-Content-Type: text/markdown
37
37
  [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)
38
38
  [![Licence](https://img.shields.io/badge/licence-MIT-green)](https://github.com/r0ny123/demangle/blob/main/LICENSE)
39
39
  [![Docs](https://img.shields.io/badge/docs-r0ny123.github.io-blue)](https://r0ny123.github.io/demangle/)
40
+ [![Open Playground](https://img.shields.io/badge/Open%20Playground-r0ny123.github.io-2ea44f?logo=googlechrome&logoColor=white)](https://r0ny123.github.io/demangle/playground/)
40
41
 
41
42
  **Read mangled symbol names in pure Python** — Itanium C++ (GCC/Clang), MSVC, Rust,
42
43
  Swift, Objective-C, Go, D, Nim, Free Pascal, Delphi, Ada/GNAT, JNI, and the pre-Itanium
@@ -89,7 +90,8 @@ pip install demangle
89
90
  Python 3.11 or newer, on CPython or PyPy. That is the whole dependency list.
90
91
 
91
92
  The documentation, API reference included, is published at
92
- <https://r0ny123.github.io/demangle/>.
93
+ <https://r0ny123.github.io/demangle/>. An interactive in-browser playground is available
94
+ at <https://r0ny123.github.io/demangle/playground/>.
93
95
 
94
96
  ## Use
95
97
 
@@ -320,6 +322,9 @@ Swift's own 217 vectors:
320
322
  ```console
321
323
  $ nm -a libfoo.so | demangle
322
324
  $ demangle _ZNSt6vectorIiSaIiEE9push_backERKi
325
+ $ demangle -b _ZN3foo3barEv # `mangled ==> demangled`
326
+ $ demangle -m _ZN3foo3barEv # only print successfully demangled symbols
327
+ $ demangle -s gnu _ZNSt6vectorIiSaIiEE9push_backERKi # choose output style (llvm, gnu)
323
328
  $ demangle --tree _Z1fPKc
324
329
  $ demangle --detect _RNvC6_123foo3bar
325
330
  $ demangle --detect --strict _ZN3Foo # the scheme that reads it, or an error
@@ -338,6 +343,7 @@ $ demangle --json _Z1fPi # the parse tree as JSON
338
343
  $ nm -a libfoo.so | demangle --json-lines # a JSON object per symbol
339
344
  $ demangle --json-lines --signature _Z1fPi # ... with the parts of the name
340
345
  $ printf '%s\0' "$name" | demangle -0 # whole names ended by NUL, in and out
346
+ $ demangle --list-languages # list supported schemes and aliases
341
347
  ```
342
348
 
343
349
  `--json-lines` writes one object per name, `{"mangled": ..., "demangled": ...,
@@ -4,6 +4,7 @@
4
4
  [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/downloads/)
5
5
  [![Licence](https://img.shields.io/badge/licence-MIT-green)](https://github.com/r0ny123/demangle/blob/main/LICENSE)
6
6
  [![Docs](https://img.shields.io/badge/docs-r0ny123.github.io-blue)](https://r0ny123.github.io/demangle/)
7
+ [![Open Playground](https://img.shields.io/badge/Open%20Playground-r0ny123.github.io-2ea44f?logo=googlechrome&logoColor=white)](https://r0ny123.github.io/demangle/playground/)
7
8
 
8
9
  **Read mangled symbol names in pure Python** — Itanium C++ (GCC/Clang), MSVC, Rust,
9
10
  Swift, Objective-C, Go, D, Nim, Free Pascal, Delphi, Ada/GNAT, JNI, and the pre-Itanium
@@ -56,7 +57,8 @@ pip install demangle
56
57
  Python 3.11 or newer, on CPython or PyPy. That is the whole dependency list.
57
58
 
58
59
  The documentation, API reference included, is published at
59
- <https://r0ny123.github.io/demangle/>.
60
+ <https://r0ny123.github.io/demangle/>. An interactive in-browser playground is available
61
+ at <https://r0ny123.github.io/demangle/playground/>.
60
62
 
61
63
  ## Use
62
64
 
@@ -287,6 +289,9 @@ Swift's own 217 vectors:
287
289
  ```console
288
290
  $ nm -a libfoo.so | demangle
289
291
  $ demangle _ZNSt6vectorIiSaIiEE9push_backERKi
292
+ $ demangle -b _ZN3foo3barEv # `mangled ==> demangled`
293
+ $ demangle -m _ZN3foo3barEv # only print successfully demangled symbols
294
+ $ demangle -s gnu _ZNSt6vectorIiSaIiEE9push_backERKi # choose output style (llvm, gnu)
290
295
  $ demangle --tree _Z1fPKc
291
296
  $ demangle --detect _RNvC6_123foo3bar
292
297
  $ demangle --detect --strict _ZN3Foo # the scheme that reads it, or an error
@@ -305,6 +310,7 @@ $ demangle --json _Z1fPi # the parse tree as JSON
305
310
  $ nm -a libfoo.so | demangle --json-lines # a JSON object per symbol
306
311
  $ demangle --json-lines --signature _Z1fPi # ... with the parts of the name
307
312
  $ printf '%s\0' "$name" | demangle -0 # whole names ended by NUL, in and out
313
+ $ demangle --list-languages # list supported schemes and aliases
308
314
  ```
309
315
 
310
316
  `--json-lines` writes one object per name, `{"mangled": ..., "demangled": ...,
@@ -91,8 +91,8 @@ name that caused it rather than being killed.
91
91
 
92
92
  | Version | Supported |
93
93
  | --- | --- |
94
- | 0.3.x | yes |
95
- | < 0.3 | no |
94
+ | 0.5.x | yes |
95
+ | < 0.5 | no |
96
96
 
97
97
  Until 1.0, security fixes land on the latest released minor version only. There is no
98
98
  long-term support branch and no backporting; upgrading to the current minor version is
@@ -0,0 +1,68 @@
1
+ {
2
+ "cold": {
3
+ "names": 14101,
4
+ "seconds": 0.648513,
5
+ "per_second": 21744,
6
+ "microseconds_each": 45.991,
7
+ "normalised": 1329.407,
8
+ "relative_to_pivot": 123.19
9
+ },
10
+ "warm": {
11
+ "names": 42303,
12
+ "seconds": 0.015793,
13
+ "per_second": 2678592,
14
+ "microseconds_each": 0.373,
15
+ "normalised": 10.792
16
+ },
17
+ "negative": {
18
+ "names": 14101,
19
+ "seconds": 0.011647,
20
+ "per_second": 1210698,
21
+ "microseconds_each": 0.826,
22
+ "normalised": 23.876,
23
+ "relative_to_pivot": 2.2124
24
+ },
25
+ "structured": {
26
+ "names": 636,
27
+ "seconds": 0.035171,
28
+ "per_second": 18083,
29
+ "microseconds_each": 55.3,
30
+ "parsed": 636,
31
+ "normalised": 1598.062,
32
+ "relative_to_pivot": 148.0849
33
+ },
34
+ "calibration": {
35
+ "seconds": 0.034605,
36
+ "rounds": 200000
37
+ },
38
+ "swift": {
39
+ "names": 256,
40
+ "seconds": 0.0181,
41
+ "per_second": 14174,
42
+ "microseconds_each": 70.55,
43
+ "succeeded": 256,
44
+ "normalised": 2303.46,
45
+ "relative_to_pivot": 336.776,
46
+ "recorded_on": "GitHub Actions ubuntu-24.04, CPython 3.13.16; run 38108232827"
47
+ },
48
+ "swift_parse": {
49
+ "names": 256,
50
+ "seconds": 0.0213,
51
+ "per_second": 12046,
52
+ "microseconds_each": 83.02,
53
+ "succeeded": 256,
54
+ "normalised": 2710.43,
55
+ "relative_to_pivot": 396.277,
56
+ "recorded_on": "GitHub Actions ubuntu-24.04, CPython 3.13.16; run 38108232827"
57
+ },
58
+ "signature": {
59
+ "names": 1280,
60
+ "seconds": 0.0963,
61
+ "per_second": 13289,
62
+ "microseconds_each": 75.25,
63
+ "succeeded": 1280,
64
+ "normalised": 2456.81,
65
+ "relative_to_pivot": 359.197,
66
+ "recorded_on": "GitHub Actions ubuntu-24.04, CPython 3.13.16; run 38108232827"
67
+ }
68
+ }
@@ -22,6 +22,10 @@ reproducible on a given interpreter, and fewer calls for the same output is stri
22
22
  less work, so it reports what the clock cannot. It is a report and not a gate: the count
23
23
  moves with the interpreter version as well as with this package, and a gate that fails
24
24
  on someone else's Python would be worse than none.
25
+
26
+ The Swift phases use a bounded prefix of the real-world corpus, so the additional AST
27
+ work stays quick. `signature` exercises extraction across several schemes without
28
+ making the main corpus-sized workloads larger.
25
29
  """
26
30
 
27
31
  import argparse
@@ -58,6 +62,7 @@ TOLERANCE = 1.25
58
62
  PIVOT = "warm"
59
63
 
60
64
  CALIBRATION_ROUNDS = 200_000
65
+ SPECIALIZED_SAMPLE_SIZE = 256
61
66
 
62
67
 
63
68
  def calibrate():
@@ -135,6 +140,11 @@ def corpus_names(*files):
135
140
  return names
136
141
 
137
142
 
143
+ def corpus_sample(filename, limit):
144
+ """Read at most `limit` manglings from one conformance corpus."""
145
+ return corpus_names(filename)[:limit]
146
+
147
+
138
148
  def time_it(function, repeats=5):
139
149
  """Best-of-N wall time. Best, not mean: the minimum is the least noisy estimator."""
140
150
  timings = []
@@ -163,6 +173,16 @@ def benchmarks():
163
173
  )
164
174
  negatives = [f"not_a_mangled_symbol_{index}" for index in range(len(sampled))]
165
175
 
176
+ # Keep these focused paths representative without making the benchmark unbounded.
177
+ swift = corpus_sample("swift-real-world.txt", SPECIALIZED_SAMPLE_SIZE)
178
+ signature_inputs = [
179
+ ("itanium", corpus_sample("itanium-real-world.txt", SPECIALIZED_SAMPLE_SIZE)),
180
+ ("msvc", corpus_sample("msvc-llvm-corpus.txt", SPECIALIZED_SAMPLE_SIZE)),
181
+ ("rust", corpus_sample("rust-real-world.txt", SPECIALIZED_SAMPLE_SIZE)),
182
+ ("go", corpus_sample("go-real-world.txt", SPECIALIZED_SAMPLE_SIZE)),
183
+ ("swift", swift),
184
+ ]
185
+
166
186
  def cold():
167
187
  demangle.cache_clear()
168
188
  for name in sampled:
@@ -193,17 +213,59 @@ def benchmarks():
193
213
  count += 1
194
214
  parsed.append(count)
195
215
 
196
- return parsed, [
197
- ("cold", cold, len(sampled)),
198
- ("warm", warm, len(sampled) * 3),
199
- ("negative", negative, len(negatives)),
200
- ("structured", structured, len(itanium) * structured_passes),
201
- ]
216
+ swift_demangled = []
217
+
218
+ def swift_demangle():
219
+ # Keep this parse-oriented measurement independent of the cache left by
220
+ # `time_it`'s earlier repeats.
221
+ demangle.cache_clear()
222
+ count = 0
223
+ for name in swift:
224
+ # `demangle` intentionally returns unsupported input unchanged. Counting
225
+ # changed spellings prevents a fast refusal from looking successful.
226
+ count += demangle.demangle(name, language="swift") != name
227
+ swift_demangled.append(count)
228
+
229
+ swift_parsed = []
230
+
231
+ def swift_parse():
232
+ count = 0
233
+ for name in swift:
234
+ with contextlib.suppress(Exception):
235
+ demangle.parse(name, language="swift")
236
+ count += 1
237
+ swift_parsed.append(count)
238
+
239
+ signatures = []
240
+
241
+ def signature():
242
+ count = 0
243
+ for language, names in signature_inputs:
244
+ for name in names:
245
+ with contextlib.suppress(Exception):
246
+ demangle.signature(name, language=language)
247
+ count += 1
248
+ signatures.append(count)
249
+
250
+ successes = {"swift": swift_demangled, "swift_parse": swift_parsed, "signature": signatures}
251
+ return (
252
+ parsed,
253
+ successes,
254
+ [
255
+ ("cold", cold, len(sampled)),
256
+ ("warm", warm, len(sampled) * 3),
257
+ ("negative", negative, len(negatives)),
258
+ ("structured", structured, len(itanium) * structured_passes),
259
+ ("swift", swift_demangle, len(swift)),
260
+ ("swift_parse", swift_parse, len(swift)),
261
+ ("signature", signature, sum(len(names) for _, names in signature_inputs)),
262
+ ],
263
+ )
202
264
 
203
265
 
204
266
  def run():
205
267
  results = {}
206
- parsed, cases = benchmarks()
268
+ parsed, successes, cases = benchmarks()
207
269
  reference = calibrate()
208
270
  for name, function, count in cases:
209
271
  if not count:
@@ -218,6 +280,9 @@ def run():
218
280
  }
219
281
  if "structured" in results:
220
282
  results["structured"]["parsed"] = parsed[-1] if parsed else 0
283
+ for name, counts in successes.items():
284
+ if name in results:
285
+ results[name]["succeeded"] = counts[-1] if counts else 0
221
286
  for data in results.values():
222
287
  data["normalised"] = round(data["seconds"] / data["names"] / reference * 1e6, 3)
223
288
 
@@ -258,7 +323,7 @@ def calls():
258
323
  import pstats
259
324
 
260
325
  counted = {}
261
- _, cases = benchmarks()
326
+ _, _, cases = benchmarks()
262
327
  for name, function, count in cases:
263
328
  if not count:
264
329
  continue
@@ -315,6 +380,12 @@ def main():
315
380
  print(f"\nstructured benchmark parsed {structured.get('parsed')} of {structured.get('names')} names")
316
381
  print("a timing that improved because the work stopped happening is not an improvement")
317
382
  return 1
383
+ for name in ("swift", "swift_parse", "signature"):
384
+ phase = results.get(name, {})
385
+ if phase.get("succeeded") != phase.get("names"):
386
+ print(f"\n{name} benchmark succeeded on {phase.get('succeeded', 0)} of {phase.get('names', 0)} names")
387
+ print("a timing that improved because the work stopped happening is not an improvement")
388
+ return 1
318
389
  # A shrunken corpus would also time as an improvement.
319
390
  shrunk = [
320
391
  (name, results[name]["names"], baseline[name]["names"])
@@ -0,0 +1,80 @@
1
+ """MkDocs hook: package the pure-Python source for the browser playground and merge standalone app."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import io
6
+ import shutil
7
+ import stat
8
+ import zipfile
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+ _ZIP_EPOCH = (1980, 1, 1, 0, 0, 0)
13
+
14
+
15
+ def build_assets(root_dir: Path | None = None) -> Path:
16
+ """Build a deterministic zipimportable archive of ``src/demangle``."""
17
+ if root_dir is None:
18
+ root_dir = Path(__file__).resolve().parent.parent
19
+
20
+ src = root_dir / "src" / "demangle"
21
+ if not (src / "__init__.py").is_file():
22
+ raise FileNotFoundError(f"demangle source package missing: {src}")
23
+
24
+ buf = io.BytesIO()
25
+ notices = [root_dir / name for name in ("LICENSE", "NOTICE")]
26
+ with zipfile.ZipFile(buf, "w") as archive:
27
+ for path in [*sorted(src.rglob("*")), *notices]:
28
+ if not path.is_file() or path.suffix == ".pyc" or "__pycache__" in path.parts:
29
+ continue
30
+ name = path.name if path in notices else path.relative_to(src.parent).as_posix()
31
+ info = zipfile.ZipInfo(name, _ZIP_EPOCH)
32
+ info.compress_type = zipfile.ZIP_DEFLATED
33
+ info.create_system = 3
34
+ info.external_attr = (stat.S_IFREG | 0o644) << 16
35
+ archive.writestr(info, path.read_bytes(), compress_type=zipfile.ZIP_DEFLATED, compresslevel=9)
36
+
37
+ archive_bytes = buf.getvalue()
38
+
39
+ # Emit to playground/assets/ (for standalone playground)
40
+ playground_assets = root_dir / "playground" / "assets"
41
+ playground_assets.mkdir(parents=True, exist_ok=True)
42
+ playground_zip = playground_assets / "demangle.zip"
43
+ playground_zip.write_bytes(archive_bytes)
44
+
45
+ # Also emit to docs/assets/ for backwards compatibility
46
+ docs_assets = root_dir / "docs" / "assets"
47
+ docs_assets.mkdir(parents=True, exist_ok=True)
48
+ docs_zip = docs_assets / "demangle.zip"
49
+ docs_zip.write_bytes(archive_bytes)
50
+
51
+ (docs_assets / "demangle.whl").unlink(missing_ok=True)
52
+ (docs_assets / "demangle_bundle.js").unlink(missing_ok=True)
53
+ (playground_assets / "demangle.whl").unlink(missing_ok=True)
54
+ (playground_assets / "demangle_bundle.js").unlink(missing_ok=True)
55
+
56
+ return playground_zip
57
+
58
+
59
+ def on_pre_build(config: Any) -> None:
60
+ """MkDocs pre-build event hook."""
61
+ build_assets()
62
+
63
+
64
+ def on_post_build(config: Any) -> None:
65
+ """MkDocs post-build event hook: merge standalone playground into site output."""
66
+ site_dir = Path(config["site_dir"])
67
+ playground_src = Path(__file__).resolve().parent.parent / "playground"
68
+ playground_dest = site_dir / "playground"
69
+ if playground_src.exists():
70
+ shutil.copytree(
71
+ playground_src,
72
+ playground_dest,
73
+ dirs_exist_ok=True,
74
+ ignore=shutil.ignore_patterns("__pycache__", "*.pyc"),
75
+ )
76
+
77
+
78
+ if __name__ == "__main__":
79
+ path = build_assets()
80
+ print(f"Generated archive: {path} ({path.stat().st_size} bytes)")
@@ -0,0 +1,34 @@
1
+ # Interactive Demangling Playground
2
+
3
+ Explore mangled symbols interactively in your browser. All demangling, scheme detection, structured signature extraction, and AST graph parsing run entirely client-side using **WebAssembly** via [Pyodide](https://pyodide.org/). Symbols stay in your browser. The runtime is downloaded from a CDN on first load; demangling needs no server requests after initialization.
4
+
5
+ <div style="margin: 2rem 0; text-align: center;">
6
+ <a href="https://r0ny123.github.io/demangle/playground/" class="md-button md-button--primary" style="font-size: 1.1rem; padding: 0.75rem 2.25rem;">
7
+ 🚀 Launch Fullscreen Playground
8
+ </a>
9
+ </div>
10
+
11
+ ## Key Features
12
+
13
+ - **100% Client-Side Privacy**: Runs locally in your browser via [Pyodide](https://pyodide.org/) WebAssembly. No symbols or code leave your machine.
14
+ - **Dedicated Web Worker**: Parsing executes in a dedicated Web Worker off the main thread, keeping the user interface completely non-blocking during large syntax graph rendering.
15
+ - **14 Scheme Coverage**: Auto-detects or manually targets all 14 supported ABI schemes:
16
+ - Itanium C++ (GCC, Clang)
17
+ - Microsoft Visual C++ (MSVC)
18
+ - Swift (including Swift 6 invertible protocol constraints)
19
+ - Rust (legacy and v0)
20
+ - D
21
+ - Go
22
+ - Nim
23
+ - Free Pascal
24
+ - Delphi / C++Builder
25
+ - Ada / GNAT
26
+ - Java Native Interface (JNI)
27
+ - Objective-C
28
+ - CodeWarrior C++
29
+ - GNU v2 (pre-Itanium g++ 2.x, cfront/ARM, Lucid, HP aCC)
30
+ - **Formatting Styles**: Switch between standard LLVM style and GNU style (spacing, template formatting).
31
+ - **Output Formats**: Full demangled signature, both (input and demangled), base name only, or signature without parameters.
32
+ - **Structured Signature Decomposition**: Unpacks symbols into qualified name, base name, namespace scope, parameter list, return type, calling convention, and qualifiers via `demangle.signature()`.
33
+ - **Interactive AST Inspector**: Explore the abstract syntax tree hierarchically with collapsible nodes, lazy pagination for large graphs, jump navigation for shared references (`$ref`), or copy complete JSON syntax graphs.
34
+ - **Permalinks & Sharing**: State is automatically encoded into URL hash fragments for one-click sharing.
@@ -58,6 +58,7 @@ A scheme's own node kinds are under its section on the [schemes page](schemes.md
58
58
  - Decorated
59
59
  - Special
60
60
  - AstBuilder
61
+ - AST_BUILDER
61
62
  - builder_for
62
63
 
63
64
  ## Reading
@@ -63,6 +63,7 @@ once, with the module that says most about it -- an options class with its optio
63
63
  - Indirection
64
64
  - FunctionType
65
65
  - Declaration
66
+ - PointerAuth
66
67
  - render
67
68
  - spelled_after
68
69
  - prefixed
@@ -5,8 +5,12 @@ repo_url: https://github.com/r0ny123/demangle
5
5
  repo_name: r0ny123/demangle
6
6
  edit_uri: edit/main/
7
7
 
8
+ hooks:
9
+ - docs/hooks.py
10
+
8
11
  nav:
9
12
  - Home: index.md
13
+ - Playground: playground.md
10
14
  - Working with the tree: analysing-a-binary.md
11
15
  - Labelling a symbol table: labelling-a-symbol-table.md
12
16
  - API reference:
@@ -0,0 +1,48 @@
1
+ # demangle Playground
2
+
3
+ [![Open Playground](https://img.shields.io/badge/Open%20Playground-r0ny123.github.io-2ea44f?logo=googlechrome&logoColor=white)](https://r0ny123.github.io/demangle/playground/)
4
+
5
+ Read, decompose and explore mangled symbol names interactively in your browser. Everything runs locally on **WebAssembly** via [Pyodide](https://pyodide.org/). Nothing to install, no backend servers, and zero network data transmission.
6
+
7
+ ## Features
8
+
9
+ - **Zero-Network Privacy**: Demangling, signature extraction, and AST parsing execute 100% client-side in WebAssembly. Your symbol names and binary details never leave your machine.
10
+ - **Real-Time Evaluation**: Instant debounced demangling as you type or paste symbols.
11
+ - **Full Scheme Coverage**: Auto-detects or explicitly overrides all 14 supported ABI schemes:
12
+ - Itanium C++ (GCC, Clang)
13
+ - Microsoft Visual C++ (MSVC)
14
+ - Swift (including Swift 6 invertible protocol constraints)
15
+ - Rust (legacy and v0)
16
+ - D
17
+ - Go
18
+ - Nim
19
+ - Free Pascal
20
+ - Delphi / C++Builder
21
+ - Ada / GNAT
22
+ - Java Native Interface (JNI)
23
+ - Objective-C
24
+ - CodeWarrior C++
25
+ - GNU v2 (pre-Itanium g++ 2.x, cfront/ARM, Lucid, HP aCC)
26
+ - **Signature Decomposition**: Deconstructs symbols into qualified name, base name, namespace/scope, parameters list, return type, calling convention, and qualifiers.
27
+ - **Interactive AST Visualizer**: Collapsible syntax graph tree view with shared reference (`$ref`) jump navigation and formatted JSON export.
28
+ - **URL Permalinks**: Automatically syncs symbol and option state into URL hash fragments (`#symbol=...&language=...`) for one-click sharing.
29
+ - **Light & Dark Themes**: Synchronized with system preferences and persistent across reloads.
30
+
31
+ ## Keyboard Shortcuts
32
+
33
+ | Shortcut | Action |
34
+ |---|---|
35
+ | `Ctrl / Cmd + K` | Focus mangled symbol input |
36
+ | `Esc` | Clear symbol input |
37
+ | `Ctrl / Cmd + Enter` | Force re-evaluation |
38
+
39
+ ## Running Locally
40
+
41
+ To run the standalone playground locally:
42
+
43
+ ```bash
44
+ # From repository root:
45
+ python -m http.server 8000
46
+ ```
47
+
48
+ Then open `http://localhost:8000/playground/` in your browser.