basedpl 0.1.62__tar.gz → 0.1.63__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 (476) hide show
  1. {basedpl-0.1.62 → basedpl-0.1.63}/Cargo.lock +10 -18
  2. {basedpl-0.1.62 → basedpl-0.1.63}/Cargo.toml +3 -5
  3. {basedpl-0.1.62 → basedpl-0.1.63}/DEV.md +15 -11
  4. {basedpl-0.1.62 → basedpl-0.1.63}/PKG-INFO +1 -1
  5. basedpl-0.1.63/editors/jetbrains/BPL.tmbundle/Syntaxes/bpl.tmLanguage.json +109 -0
  6. basedpl-0.1.63/editors/jetbrains/BPL.tmbundle/Syntaxes/hpl.tmLanguage.json +61 -0
  7. {basedpl-0.1.62 → basedpl-0.1.63}/editors/jetbrains/README.md +1 -1
  8. basedpl-0.1.63/editors/vim/syntax/bpl.vim +33 -0
  9. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/_quarto.yml +1 -1
  10. basedpl-0.1.63/nbs/bpl.xml +52 -0
  11. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/hanzi-notation-zh.ipynb +1 -1
  12. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/hanzi-notation.ipynb +1 -1
  13. basedpl-0.1.63/nbs/hpl.xml +40 -0
  14. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/llms.txt +1 -1
  15. basedpl-0.1.63/nbs/playground/hpl.tmLanguage.json +61 -0
  16. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/styles.css +17 -16
  17. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/syntax.qmd +2 -2
  18. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/prefs.qmd +3 -3
  19. {basedpl-0.1.62 → basedpl-0.1.63}/py/src/lib.rs +7 -9
  20. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/__init__.py +1 -1
  21. basedpl-0.1.63/python/basedpl/bpl.tmLanguage.json +109 -0
  22. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/bpltests.py +44 -8
  23. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/editors.py +56 -20
  24. basedpl-0.1.63/python/basedpl/hpl.tmLanguage.json +61 -0
  25. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/notebook_runner.py +4 -2
  26. {basedpl-0.1.62 → basedpl-0.1.63}/src/array/storage.rs +1 -1
  27. {basedpl-0.1.62 → basedpl-0.1.63}/src/array.rs +6 -6
  28. {basedpl-0.1.62 → basedpl-0.1.63}/src/batch.rs +28 -31
  29. {basedpl-0.1.62 → basedpl-0.1.63}/src/data.rs +1 -1
  30. {basedpl-0.1.62 → basedpl-0.1.63}/src/derivative.rs +23 -29
  31. {basedpl-0.1.62 → basedpl-0.1.63}/src/display.rs +23 -23
  32. {basedpl-0.1.62 → basedpl-0.1.63}/src/distribution.rs +7 -7
  33. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/assign.rs +33 -33
  34. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/binder.rs +19 -16
  35. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/idioms.rs +9 -9
  36. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/operators.rs +63 -89
  37. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/session.rs +182 -174
  38. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/tree.rs +4 -4
  39. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval.rs +88 -65
  40. {basedpl-0.1.62 → basedpl-0.1.63}/src/execution.rs +23 -3
  41. {basedpl-0.1.62 → basedpl-0.1.63}/src/explain.rs +38 -14
  42. {basedpl-0.1.62 → basedpl-0.1.63}/src/fusion/blocks.rs +11 -16
  43. {basedpl-0.1.62 → basedpl-0.1.63}/src/fusion.rs +42 -89
  44. {basedpl-0.1.62 → basedpl-0.1.63}/src/js.rs +2 -2
  45. {basedpl-0.1.62 → basedpl-0.1.63}/src/json.rs +1 -1
  46. {basedpl-0.1.62 → basedpl-0.1.63}/src/keyed.rs +1 -1
  47. {basedpl-0.1.62 → basedpl-0.1.63}/src/lib.rs +1 -0
  48. {basedpl-0.1.62 → basedpl-0.1.63}/src/linear.rs +20 -24
  49. {basedpl-0.1.62 → basedpl-0.1.63}/src/number.rs +10 -18
  50. {basedpl-0.1.62 → basedpl-0.1.63}/src/optimize.rs +6 -6
  51. {basedpl-0.1.62 → basedpl-0.1.63}/src/pervasive.rs +24 -26
  52. {basedpl-0.1.62 → basedpl-0.1.63}/src/primitive/indexing.rs +48 -51
  53. {basedpl-0.1.62 → basedpl-0.1.63}/src/primitive/search.rs +13 -14
  54. {basedpl-0.1.62 → basedpl-0.1.63}/src/primitive/structural.rs +6 -5
  55. {basedpl-0.1.62 → basedpl-0.1.63}/src/primitive.rs +69 -41
  56. {basedpl-0.1.62 → basedpl-0.1.63}/src/reference.rs +155 -100
  57. {basedpl-0.1.62 → basedpl-0.1.63}/src/search.rs +6 -6
  58. {basedpl-0.1.62 → basedpl-0.1.63}/src/selection.rs +2 -2
  59. basedpl-0.1.63/src/settings.rs +71 -0
  60. {basedpl-0.1.62 → basedpl-0.1.63}/src/symbols.rs +1 -1
  61. {basedpl-0.1.62 → basedpl-0.1.63}/src/syntax.rs +5 -9
  62. {basedpl-0.1.62 → basedpl-0.1.63}/src/system.rs +2 -2
  63. {basedpl-0.1.62 → basedpl-0.1.63}/src/timing.rs +22 -9
  64. {basedpl-0.1.62 → basedpl-0.1.63}/src/transform.rs +27 -33
  65. basedpl-0.1.63/tests/common/mod.rs +56 -0
  66. {basedpl-0.1.62 → basedpl-0.1.63}/tests/core.rs +3 -241
  67. {basedpl-0.1.62 → basedpl-0.1.63}/tests/highlighting.mjs +17 -11
  68. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/README.md +3 -3
  69. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/core.bpl +57 -103
  70. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/distributions.bpl +11 -11
  71. basedpl-0.1.63/tests/reference/static-int32.bpl +11 -0
  72. basedpl-0.1.63/tests/reference/static.bpl +23 -0
  73. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference.rs +15 -15
  74. basedpl-0.1.63/tests/settings.rs +205 -0
  75. {basedpl-0.1.62 → basedpl-0.1.63}/tests/speed.txt +93 -78
  76. basedpl-0.1.62/editors/jetbrains/BPL.tmbundle/Syntaxes/bpl.tmLanguage.json +0 -108
  77. basedpl-0.1.62/editors/vim/syntax/bpl.vim +0 -33
  78. basedpl-0.1.62/nbs/bpl.xml +0 -52
  79. basedpl-0.1.62/python/basedpl/bpl.tmLanguage.json +0 -108
  80. {basedpl-0.1.62 → basedpl-0.1.63}/.cargo/config.toml +0 -0
  81. {basedpl-0.1.62 → basedpl-0.1.63}/.gitattributes +0 -0
  82. {basedpl-0.1.62 → basedpl-0.1.63}/.github/workflows/ci.yml +0 -0
  83. {basedpl-0.1.62 → basedpl-0.1.63}/.github/workflows/docs.yml +0 -0
  84. {basedpl-0.1.62 → basedpl-0.1.63}/.github/workflows/speed.yml +0 -0
  85. {basedpl-0.1.62 → basedpl-0.1.63}/.github/workflows/test.yml +0 -0
  86. {basedpl-0.1.62 → basedpl-0.1.63}/.gitignore +0 -0
  87. {basedpl-0.1.62 → basedpl-0.1.63}/CONTRIBUTING.md +0 -0
  88. {basedpl-0.1.62 → basedpl-0.1.63}/LICENSE +0 -0
  89. {basedpl-0.1.62 → basedpl-0.1.63}/README.md +0 -0
  90. {basedpl-0.1.62 → basedpl-0.1.63}/_config.yml +0 -0
  91. {basedpl-0.1.62 → basedpl-0.1.63}/_layouts/default.html +0 -0
  92. {basedpl-0.1.62 → basedpl-0.1.63}/build.rs +0 -0
  93. {basedpl-0.1.62 → basedpl-0.1.63}/editors/jetbrains/BPL.tmbundle/info.plist +0 -0
  94. {basedpl-0.1.62 → basedpl-0.1.63}/editors/jetbrains/BPL.xml +0 -0
  95. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Info.plist +0 -0
  96. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.icns +0 -0
  97. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.keylayout +0 -0
  98. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  99. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/version.plist +0 -0
  100. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-de.txt +0 -0
  101. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Info.plist +0 -0
  102. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.icns +0 -0
  103. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.keylayout +0 -0
  104. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  105. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/version.plist +0 -0
  106. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-es.txt +0 -0
  107. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Info.plist +0 -0
  108. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.icns +0 -0
  109. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.keylayout +0 -0
  110. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  111. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/version.plist +0 -0
  112. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-fr.txt +0 -0
  113. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Info.plist +0 -0
  114. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.icns +0 -0
  115. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.keylayout +0 -0
  116. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  117. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/version.plist +0 -0
  118. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-uk.txt +0 -0
  119. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Info.plist +0 -0
  120. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.icns +0 -0
  121. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.keylayout +0 -0
  122. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  123. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/version.plist +0 -0
  124. {basedpl-0.1.62 → basedpl-0.1.63}/editors/macos/BasedPL-us.txt +0 -0
  125. {basedpl-0.1.62 → basedpl-0.1.63}/editors/vim/ftdetect/bpl.vim +0 -0
  126. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/README.md +0 -0
  127. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/build.ps1 +0 -0
  128. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/install.ps1 +0 -0
  129. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/keyboard.c +0 -0
  130. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/keyboard.def +0 -0
  131. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/keyboard.rc +0 -0
  132. {basedpl-0.1.62 → basedpl-0.1.63}/editors/windows/layout.h +0 -0
  133. {basedpl-0.1.62 → basedpl-0.1.63}/index_files/figure-commonmark/cell-17-output-1.svg +0 -0
  134. {basedpl-0.1.62 → basedpl-0.1.63}/index_files/figure-commonmark/cell-18-output-1.svg +0 -0
  135. {basedpl-0.1.62 → basedpl-0.1.63}/index_files/figure-html/cell-17-output-1.svg +0 -0
  136. {basedpl-0.1.62 → basedpl-0.1.63}/index_files/figure-html/cell-18-output-1.svg +0 -0
  137. {basedpl-0.1.62 → basedpl-0.1.63}/lib/LICENSE-april +0 -0
  138. {basedpl-0.1.62 → basedpl-0.1.63}/lib/README.md +0 -0
  139. {basedpl-0.1.62 → basedpl-0.1.63}/lib/array.bpl +0 -0
  140. {basedpl-0.1.62 → basedpl-0.1.63}/lib/dyalog.bpl +0 -0
  141. {basedpl-0.1.62 → basedpl-0.1.63}/lib/graph.bpl +0 -0
  142. {basedpl-0.1.62 → basedpl-0.1.63}/lib/numeric.bpl +0 -0
  143. {basedpl-0.1.62 → basedpl-0.1.63}/lib/power.bpl +0 -0
  144. {basedpl-0.1.62 → basedpl-0.1.63}/lib/regex.bpl +0 -0
  145. {basedpl-0.1.62 → basedpl-0.1.63}/lib/string.bpl +0 -0
  146. {basedpl-0.1.62 → basedpl-0.1.63}/lib/tree.bpl +0 -0
  147. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/.gitignore +0 -0
  148. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/arrays.ipynb +0 -0
  149. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/assignment.ipynb +0 -0
  150. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/bqn.xml +0 -0
  151. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/bracket-types.ipynb +0 -0
  152. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/cli.qmd +0 -0
  153. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/comparison.qmd +0 -0
  154. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/data.ipynb +0 -0
  155. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/dfns.ipynb +0 -0
  156. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/distributions.ipynb +0 -0
  157. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/driver.js +0 -0
  158. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/dyalog.ipynb +0 -0
  159. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/dyalog.xml +0 -0
  160. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/evaluation.qmd +0 -0
  161. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/fonts/LICENSE-SAX2 +0 -0
  162. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/fonts/README.md +0 -0
  163. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/fonts/SAX2B.ttf +0 -0
  164. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/fonts/SAX2B.woff2 +0 -0
  165. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/fonts.css +0 -0
  166. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/attractor.bpl +0 -0
  167. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/boids.bpl +0 -0
  168. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/dragon.bpl +0 -0
  169. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/flow.bpl +0 -0
  170. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/mandelbrot.bpl +0 -0
  171. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/mandelbrot32.bpl +0 -0
  172. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/orbits.bpl +0 -0
  173. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/phyllotaxis.bpl +0 -0
  174. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/prefs.bpl +0 -0
  175. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery/reaction.bpl +0 -0
  176. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/gallery.qmd +0 -0
  177. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/getting-started.ipynb +0 -0
  178. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/_metadata.yml +0 -0
  179. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/alpha-underbar.qmd +0 -0
  180. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/alpha.qmd +0 -0
  181. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/at.qmd +0 -0
  182. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/backslash-bar.qmd +0 -0
  183. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/backslash.qmd +0 -0
  184. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/braces.qmd +0 -0
  185. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/brackets.qmd +0 -0
  186. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/bullet.qmd +0 -0
  187. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-backslash.qmd +0 -0
  188. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-bar.qmd +0 -0
  189. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-diaeresis.qmd +0 -0
  190. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-divide.qmd +0 -0
  191. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-slash.qmd +0 -0
  192. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-star.qmd +0 -0
  193. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-stile.qmd +0 -0
  194. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle-times.qmd +0 -0
  195. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/circle.qmd +0 -0
  196. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/colon.qmd +0 -0
  197. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/comma-bar.qmd +0 -0
  198. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/comma.qmd +0 -0
  199. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/del-diaeresis.qmd +0 -0
  200. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/del-stile.qmd +0 -0
  201. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/del.qmd +0 -0
  202. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/delta-stile.qmd +0 -0
  203. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/diaeresis.qmd +0 -0
  204. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/diamond-underbar.qmd +0 -0
  205. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/diamond.qmd +0 -0
  206. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/domino.qmd +0 -0
  207. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/dot.qmd +0 -0
  208. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/down-arrow.qmd +0 -0
  209. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/down-shoe.qmd +0 -0
  210. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/down-tack.qmd +0 -0
  211. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/downstile.qmd +0 -0
  212. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/epsilon-underbar.qmd +0 -0
  213. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/epsilon.qmd +0 -0
  214. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/equal-underbar-slash.qmd +0 -0
  215. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/equal-underbar.qmd +0 -0
  216. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/equals.qmd +0 -0
  217. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/error-guard.qmd +0 -0
  218. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/exclamation.qmd +0 -0
  219. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/greater-than-or-equal.qmd +0 -0
  220. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/greater-than.qmd +0 -0
  221. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/hash.qmd +0 -0
  222. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/hydrant.qmd +0 -0
  223. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/infinity.qmd +0 -0
  224. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/inverted-question.qmd +0 -0
  225. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/iota-underbar.qmd +0 -0
  226. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/iota.qmd +0 -0
  227. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/jot-diaeresis.qmd +0 -0
  228. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/jot.qmd +0 -0
  229. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/lamp.qmd +0 -0
  230. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/left-arrow.qmd +0 -0
  231. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/left-shoe-underbar.qmd +0 -0
  232. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/left-shoe.qmd +0 -0
  233. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/left-tack.qmd +0 -0
  234. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/left-tail-arrow.qmd +0 -0
  235. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/less-than-or-equal.qmd +0 -0
  236. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/less-than.qmd +0 -0
  237. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/minus.qmd +0 -0
  238. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/not-equals.qmd +0 -0
  239. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/obelus.qmd +0 -0
  240. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/omega-underbar.qmd +0 -0
  241. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/omega.qmd +0 -0
  242. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/overbar.qmd +0 -0
  243. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/parentheses.qmd +0 -0
  244. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/partial.qmd +0 -0
  245. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/pi.qmd +0 -0
  246. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/plus.qmd +0 -0
  247. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/quad-colon.qmd +0 -0
  248. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/quad-diamond.qmd +0 -0
  249. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/quad-equal.qmd +0 -0
  250. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/quad-jot.qmd +0 -0
  251. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/quad.qmd +0 -0
  252. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/question.qmd +0 -0
  253. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/quote.qmd +0 -0
  254. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/radical.qmd +0 -0
  255. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/rho.qmd +0 -0
  256. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/right-arrow-from-bar.qmd +0 -0
  257. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/right-left-arrows.qmd +0 -0
  258. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/right-shoe.qmd +0 -0
  259. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/right-tack.qmd +0 -0
  260. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/right-tail-arrow.qmd +0 -0
  261. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/slash-bar.qmd +0 -0
  262. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/slash.qmd +0 -0
  263. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/squad.qmd +0 -0
  264. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/star-diaeresis.qmd +0 -0
  265. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/star.qmd +0 -0
  266. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/stile-tilde.qmd +0 -0
  267. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/stile.qmd +0 -0
  268. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/superscript-b.qmd +0 -0
  269. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/thorn.qmd +0 -0
  270. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/tilde-diaeresis.qmd +0 -0
  271. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/tilde.qmd +0 -0
  272. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/times.qmd +0 -0
  273. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/up-arrow.qmd +0 -0
  274. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/up-down-arrow.qmd +0 -0
  275. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/up-shoe.qmd +0 -0
  276. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/up-tack.qmd +0 -0
  277. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/upstile.qmd +0 -0
  278. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/vee-bar.qmd +0 -0
  279. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/vee.qmd +0 -0
  280. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/wedge-bar.qmd +0 -0
  281. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/wedge.qmd +0 -0
  282. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs/zilde.qmd +0 -0
  283. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs-study.qmd +0 -0
  284. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/glyphs.qmd +0 -0
  285. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/index.ipynb +0 -0
  286. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/indexing.ipynb +0 -0
  287. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/introspection.ipynb +0 -0
  288. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/keyboard.qmd +0 -0
  289. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/keyed.ipynb +0 -0
  290. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/magics.ipynb +0 -0
  291. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/modules.qmd +0 -0
  292. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/nbdev.yml +0 -0
  293. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/notebooks.ipynb +0 -0
  294. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/numbers.qmd +0 -0
  295. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/overview.ipynb +0 -0
  296. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/papers/aplwiki-arrays.md +0 -0
  297. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/papers/brickman-depth-1-scalars.md +0 -0
  298. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/papers/mercer-based-system.md +0 -0
  299. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/playground/bpl.js +0 -0
  300. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/playground/gallery.js +0 -0
  301. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/playground/monaco-worker.js +0 -0
  302. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/playground/page.js +0 -0
  303. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/playground/worker.js +0 -0
  304. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/playground.qmd +0 -0
  305. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/plot.ipynb +0 -0
  306. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/principles.ipynb +0 -0
  307. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/processes.qmd +0 -0
  308. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/puppy.jpg +0 -0
  309. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/python.ipynb +0 -0
  310. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/regex.ipynb +0 -0
  311. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/repl.qmd +0 -0
  312. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/scripts.ipynb +0 -0
  313. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/sidebar.yml +0 -0
  314. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/strings.ipynb +0 -0
  315. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/01_basics.ipynb +0 -0
  316. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/02_functions.ipynb +0 -0
  317. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/03_operators.ipynb +0 -0
  318. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/04_nested-arrays.ipynb +0 -0
  319. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/05_searching-indexing.ipynb +0 -0
  320. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/06_rearranging-arrays.ipynb +0 -0
  321. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/study/07_numerical-tools.ipynb +0 -0
  322. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/style.qmd +0 -0
  323. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/_metadata.yml +0 -0
  324. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/c.qmd +0 -0
  325. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/canvas.qmd +0 -0
  326. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/constants.qmd +0 -0
  327. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/copy.qmd +0 -0
  328. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/csv.qmd +0 -0
  329. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/date.qmd +0 -0
  330. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/decompose.qmd +0 -0
  331. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/deflate.qmd +0 -0
  332. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/delay.qmd +0 -0
  333. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/detach.qmd +0 -0
  334. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/distribution.qmd +0 -0
  335. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/edge.qmd +0 -0
  336. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/element.qmd +0 -0
  337. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/ex.qmd +0 -0
  338. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/explain.qmd +0 -0
  339. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/fetch.qmd +0 -0
  340. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/float.qmd +0 -0
  341. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/hash.qmd +0 -0
  342. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/host.qmd +0 -0
  343. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/image.qmd +0 -0
  344. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/index.qmd +0 -0
  345. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/js.qmd +0 -0
  346. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/json.qmd +0 -0
  347. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/literal.qmd +0 -0
  348. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/load.qmd +0 -0
  349. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/memory.qmd +0 -0
  350. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/metadata.qmd +0 -0
  351. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/mime.qmd +0 -0
  352. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/mkdir.qmd +0 -0
  353. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/nc.qmd +0 -0
  354. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/nget.qmd +0 -0
  355. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/nl.qmd +0 -0
  356. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/normalize.qmd +0 -0
  357. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/nput.qmd +0 -0
  358. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/path.qmd +0 -0
  359. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/plot.qmd +0 -0
  360. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/r.qmd +0 -0
  361. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/rand.qmd +0 -0
  362. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/readdir.qmd +0 -0
  363. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/remove.qmd +0 -0
  364. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/rename.qmd +0 -0
  365. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/signal.qmd +0 -0
  366. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/src.qmd +0 -0
  367. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/storage.qmd +0 -0
  368. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/svg.qmd +0 -0
  369. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/time.qmd +0 -0
  370. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/ucs.qmd +0 -0
  371. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/uuid.qmd +0 -0
  372. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/vfi.qmd +0 -0
  373. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system/xml.qmd +0 -0
  374. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/system-functions.qmd +0 -0
  375. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/terms.qmd +0 -0
  376. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/web.ipynb +0 -0
  377. {basedpl-0.1.62 → basedpl-0.1.63}/nbs/xml.ipynb +0 -0
  378. {basedpl-0.1.62 → basedpl-0.1.63}/package-lock.json +0 -0
  379. {basedpl-0.1.62 → basedpl-0.1.63}/package.json +0 -0
  380. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/README.md +0 -0
  381. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/aplcart.jsonl +0 -0
  382. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/april.jsonl +0 -0
  383. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/bqn.jsonl +0 -0
  384. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/core.jsonl +0 -0
  385. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/dyalog.jsonl +0 -0
  386. {basedpl-0.1.62 → basedpl-0.1.63}/provenance/ngn.jsonl +0 -0
  387. {basedpl-0.1.62 → basedpl-0.1.63}/py/Cargo.toml +0 -0
  388. {basedpl-0.1.62 → basedpl-0.1.63}/py/build.rs +0 -0
  389. {basedpl-0.1.62 → basedpl-0.1.63}/pyproject.toml +0 -0
  390. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/_modidx.py +0 -0
  391. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/dyalog.py +0 -0
  392. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/font.py +0 -0
  393. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/fonts.css +0 -0
  394. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/functions.py +0 -0
  395. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/input.js +0 -0
  396. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/ipython.py +0 -0
  397. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/keyboards.json +0 -0
  398. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/keyboards.py +0 -0
  399. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/layout.json +0 -0
  400. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/lb.js +0 -0
  401. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/notebooks.py +0 -0
  402. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/printing.py +0 -0
  403. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/reference.py +0 -0
  404. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/syntax.py +0 -0
  405. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/windows_keyboard.py +0 -0
  406. {basedpl-0.1.62 → basedpl-0.1.63}/python/basedpl/worker.py +0 -0
  407. {basedpl-0.1.62 → basedpl-0.1.63}/rustfmt.toml +0 -0
  408. {basedpl-0.1.62 → basedpl-0.1.63}/scripts/install-macos.sh +0 -0
  409. {basedpl-0.1.62 → basedpl-0.1.63}/scripts/prep.py +0 -0
  410. {basedpl-0.1.62 → basedpl-0.1.63}/src/agreement.rs +0 -0
  411. {basedpl-0.1.62 → basedpl-0.1.63}/src/array/text.rs +0 -0
  412. {basedpl-0.1.62 → basedpl-0.1.63}/src/canvas.js +0 -0
  413. {basedpl-0.1.62 → basedpl-0.1.63}/src/canvas.rs +0 -0
  414. {basedpl-0.1.62 → basedpl-0.1.63}/src/csv.rs +0 -0
  415. {basedpl-0.1.62 → basedpl-0.1.63}/src/date.rs +0 -0
  416. {basedpl-0.1.62 → basedpl-0.1.63}/src/element.rs +0 -0
  417. {basedpl-0.1.62 → basedpl-0.1.63}/src/error.rs +0 -0
  418. {basedpl-0.1.62 → basedpl-0.1.63}/src/eval/dissect.rs +0 -0
  419. {basedpl-0.1.62 → basedpl-0.1.63}/src/files.rs +0 -0
  420. {basedpl-0.1.62 → basedpl-0.1.63}/src/host.rs +0 -0
  421. {basedpl-0.1.62 → basedpl-0.1.63}/src/host_web.rs +0 -0
  422. {basedpl-0.1.62 → basedpl-0.1.63}/src/image/codecs.rs +0 -0
  423. {basedpl-0.1.62 → basedpl-0.1.63}/src/image/imageio.rs +0 -0
  424. {basedpl-0.1.62 → basedpl-0.1.63}/src/image.rs +0 -0
  425. {basedpl-0.1.62 → basedpl-0.1.63}/src/inspection.rs +0 -0
  426. {basedpl-0.1.62 → basedpl-0.1.63}/src/number_theory.rs +0 -0
  427. {basedpl-0.1.62 → basedpl-0.1.63}/src/plot.rs +0 -0
  428. {basedpl-0.1.62 → basedpl-0.1.63}/src/polynomial.rs +0 -0
  429. {basedpl-0.1.62 → basedpl-0.1.63}/src/primitive/numeric.rs +0 -0
  430. {basedpl-0.1.62 → basedpl-0.1.63}/src/protocol.rs +0 -0
  431. {basedpl-0.1.62 → basedpl-0.1.63}/src/regex.rs +0 -0
  432. {basedpl-0.1.62 → basedpl-0.1.63}/src/xml.rs +0 -0
  433. {basedpl-0.1.62 → basedpl-0.1.63}/tests/conftest.py +0 -0
  434. {basedpl-0.1.62 → basedpl-0.1.63}/tests/derivatives.rs +0 -0
  435. {basedpl-0.1.62 → basedpl-0.1.63}/tests/explain.rs +0 -0
  436. {basedpl-0.1.62 → basedpl-0.1.63}/tests/input.mjs +0 -0
  437. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/LICENSE-aplcart +0 -0
  438. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/LICENSE-april +0 -0
  439. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/LICENSE-bqn +0 -0
  440. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/LICENSE-bqncrate +0 -0
  441. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/LICENSE-dyalog +0 -0
  442. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/LICENSE-ngn +0 -0
  443. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/aplcart.bpl +0 -0
  444. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/april.bpl +0 -0
  445. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/bqn.bpl +0 -0
  446. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/dyalog.bpl +0 -0
  447. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/graphics.bpl +0 -0
  448. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/lib.bpl +0 -0
  449. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/ngn.bpl +0 -0
  450. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/regex.bpl +0 -0
  451. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/support/april.bpl +0 -0
  452. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/support/avl.bpl +0 -0
  453. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/support/redblack.bpl +0 -0
  454. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/support/sbst.bpl +0 -0
  455. {basedpl-0.1.62 → basedpl-0.1.63}/tests/reference/support/splay.bpl +0 -0
  456. {basedpl-0.1.62 → basedpl-0.1.63}/tests/scaling.rs +0 -0
  457. {basedpl-0.1.62 → basedpl-0.1.63}/tests/speed.rs +0 -0
  458. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_api.py +0 -0
  459. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_basic.py +0 -0
  460. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_bpltests.py +0 -0
  461. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_glyphs.py +0 -0
  462. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_graphics.py +0 -0
  463. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_ipython.py +0 -0
  464. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_kernel.py +0 -0
  465. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_keylayout.py +0 -0
  466. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_notebooks.py +0 -0
  467. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_reference.py +0 -0
  468. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_repl.py +0 -0
  469. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_windows_keyboard.py +0 -0
  470. {basedpl-0.1.62 → basedpl-0.1.63}/tests/test_worker.py +0 -0
  471. {basedpl-0.1.62 → basedpl-0.1.63}/tests/units.rs +0 -0
  472. {basedpl-0.1.62 → basedpl-0.1.63}/tests/wasm-pkg.mjs +0 -0
  473. {basedpl-0.1.62 → basedpl-0.1.63}/tests/wasm-speed.mjs +0 -0
  474. {basedpl-0.1.62 → basedpl-0.1.63}/tests/wasm.mjs +0 -0
  475. {basedpl-0.1.62 → basedpl-0.1.63}/tests/windows_keyboard.c +0 -0
  476. {basedpl-0.1.62 → basedpl-0.1.63}/wheel/data/share/jupyter/kernels/bpl/kernel.json +0 -0
@@ -93,14 +93,13 @@ checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
93
93
 
94
94
  [[package]]
95
95
  name = "basedpl"
96
- version = "0.1.62"
96
+ version = "0.1.63"
97
97
  dependencies = [
98
98
  "base64 0.23.1",
99
99
  "bytemuck",
100
100
  "chrono",
101
101
  "csv",
102
102
  "flate2",
103
- "foldhash",
104
103
  "getrandom",
105
104
  "globset",
106
105
  "half",
@@ -128,7 +127,6 @@ dependencies = [
128
127
  "stacker",
129
128
  "strength_reduce",
130
129
  "tempfile",
131
- "unicode-script",
132
130
  "unicode-width",
133
131
  "uuid",
134
132
  "walkdir",
@@ -139,12 +137,11 @@ dependencies = [
139
137
 
140
138
  [[package]]
141
139
  name = "basedpl-cli"
142
- version = "0.1.62"
140
+ version = "0.1.63"
143
141
  dependencies = [
144
142
  "async-trait",
145
143
  "basedpl",
146
144
  "ctrlc",
147
- "foldhash",
148
145
  "kernmini",
149
146
  "rustyline",
150
147
  "serde",
@@ -153,7 +150,7 @@ dependencies = [
153
150
 
154
151
  [[package]]
155
152
  name = "basedpl-py"
156
- version = "0.1.62"
153
+ version = "0.1.63"
157
154
  dependencies = [
158
155
  "basedpl",
159
156
  "num-bigint",
@@ -168,7 +165,7 @@ dependencies = [
168
165
 
169
166
  [[package]]
170
167
  name = "basedpl-wasm"
171
- version = "0.1.62"
168
+ version = "0.1.63"
172
169
  dependencies = [
173
170
  "basedpl",
174
171
  "js-sys",
@@ -1416,10 +1413,11 @@ dependencies = [
1416
1413
 
1417
1414
  [[package]]
1418
1415
  name = "rustymath"
1419
- version = "0.1.39"
1416
+ version = "0.1.40"
1420
1417
  source = "registry+https://github.com/rust-lang/crates.io-index"
1421
- checksum = "5f59fec09559e65a8eea738822e6547394755ee66b00aeb4173a79c230764692"
1418
+ checksum = "4dc5f83f6e77929139aa2a0080425cb483f6fedae447ae40bc788031fca80a01"
1422
1419
  dependencies = [
1420
+ "foldhash",
1423
1421
  "half",
1424
1422
  "hashbrown 0.17.1",
1425
1423
  "libc",
@@ -1435,9 +1433,9 @@ dependencies = [
1435
1433
 
1436
1434
  [[package]]
1437
1435
  name = "rustymath-buffer"
1438
- version = "0.1.39"
1436
+ version = "0.1.40"
1439
1437
  source = "registry+https://github.com/rust-lang/crates.io-index"
1440
- checksum = "645c80d2fe9aafe3866967008960bfbe9c15c126b17a717184ee67352110bb43"
1438
+ checksum = "74411856ed0b141e1e64c63eea50ce5bb7cbef0a30f9b310e19fe81d1e83d72d"
1441
1439
  dependencies = [
1442
1440
  "pyo3",
1443
1441
  "rustymath",
@@ -1783,12 +1781,6 @@ version = "1.0.27"
1783
1781
  source = "registry+https://github.com/rust-lang/crates.io-index"
1784
1782
  checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
1785
1783
 
1786
- [[package]]
1787
- name = "unicode-script"
1788
- version = "0.5.8"
1789
- source = "registry+https://github.com/rust-lang/crates.io-index"
1790
- checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee"
1791
-
1792
1784
  [[package]]
1793
1785
  name = "unicode-segmentation"
1794
1786
  version = "1.13.3"
@@ -2093,7 +2085,7 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
2093
2085
 
2094
2086
  [[package]]
2095
2087
  name = "xtask"
2096
- version = "0.1.62"
2088
+ version = "0.1.63"
2097
2089
  dependencies = [
2098
2090
  "anyhow",
2099
2091
  "rustymath",
@@ -5,14 +5,14 @@ members = ["py"]
5
5
  join_comments = true
6
6
 
7
7
  [workspace.package]
8
- version = "0.1.62"
8
+ version = "0.1.63"
9
9
  edition = "2024"
10
10
  rust-version = "1.98"
11
11
  license = "Apache-2.0"
12
12
 
13
13
  [workspace.dependencies]
14
- rustymath = { version = ">=0.1.39, <1", default-features = false }
15
- rustymath-buffer = ">=0.1.39, <1"
14
+ rustymath = { version = ">=0.1.40, <1", default-features = false }
15
+ rustymath-buffer = ">=0.1.40, <1"
16
16
  pyo3 = ">=0.29.2, <1"
17
17
  pyo3-build-config = ">=0.29.2, <1"
18
18
 
@@ -60,7 +60,6 @@ tempfile = "3"
60
60
  serde = ">=1.0.229, <2"
61
61
  serde_json = { version = "1", features = ["arbitrary_precision", "preserve_order"] }
62
62
  unicode-width = { version = ">=0.2.2, <1", default-features = false }
63
- unicode-script = "0.5"
64
63
  num-rational = ">=0.4.2, <1"
65
64
  num-complex = { version = ">=0.4.6, <1", features = ["bytemuck"] }
66
65
  num-bigint = ">=0.4.6, <0.5"
@@ -73,7 +72,6 @@ rand = { version = ">=0.10.2, <1", features = ["chacha"] }
73
72
  plotters = { git = "https://github.com/AnswerDotAI/plotters.git", branch = "master", default-features = false, features = ["svg_backend", "colormaps", "full_palette"] }
74
73
  base64 = ">=0.22.1, <1"
75
74
  stacker = ">=0.1.25, <1"
76
- foldhash = ">=0.2.0, <1"
77
75
  bytemuck = { version = ">=1.25.2, <2", features = ["extern_crate_alloc"] }
78
76
  json5 = ">=1.3.1, <2"
79
77
  roxmltree = { version = ">=0.21.1, <1", default-features = false, features = ["std"] }
@@ -28,7 +28,9 @@ An already-running Python process retains its loaded extension. In a kernel, use
28
28
 
29
29
  Measure with `BASEDPL_COSTS=1 cargo test --test speed` or `basedpl.bpltests.time_cases(cases)`. Both count costs in copies. A copy is the time to write as many floats as the data has items, each negated, into a second buffer. Budgets are single-thread measurements. Use `time_cases(..., threads=...)` separately for scaling. `speed_costs()` reads the cases in `tests/speed.txt`. `cases=` selects expressions, `wasm=DIR` selects a browser build, `bpl=PATH` selects another native `bpl`, such as a saved copy, and `native=True` times rustymath's own linear algebra, which dev builds compile in. `logged_costs(log)` reads CI output. `cargo_costs(path)` runs either project's Rust speed test, and `pytest_costs(path)` runs rustymath's Python speed test.
30
30
 
31
- `bpl-tests NAME ARGUMENT...` runs one of these functions from the shell and prints its result: `check_file`, `check_page`, `time_cases`, `speed_costs`, `cargo_costs`, `pytest_costs` or `wasm_test`. Run long checks and timings this way, not in the shared kernel, which runs one cell at a time for every agent. For example, `bpl-tests time_cases '+/v' --threads 4` times `+/v` on four threads. `time_cases` and `speed_costs` take cases as positional arguments. When a case starts with `-`, put the cases last, after `--`, as in `bpl-tests speed_costs -- '-.×m' '+/v'`. `bpl-tests NAME -h` lists a function's arguments.
31
+ Costs in copies can't show a per-call change of a few percent, because code layout alone moves a timing by more than that. `instructions(cases)` counts instructions, which load and layout don't change. Each case is BPL that makes one call per step of `N`, such as `{⍵}⍣N⊢0`. A map such as `f¨N⍴0` calls a dfn once on all its cells, so it gives no per-call cost. It runs fresh single-threaded `bpl` processes at two values of `N` and reports the instructions retired per unit of `N`, so startup and `setup=` cancel out. It reads `/usr/bin/time -l` on macOS and `perf stat` on Linux, and `bpl=PATH` counts a saved copy.
32
+
33
+ `bpl-tests NAME ARGUMENT...` runs one of these functions from the shell and prints its result: `check_file`, `check_page`, `time_cases`, `instructions`, `speed_costs`, `cargo_costs`, `pytest_costs` or `wasm_test`. Run long checks and timings this way, not in the shared kernel, which runs one cell at a time for every agent. For example, `bpl-tests time_cases '+/v' --threads 4` times `+/v` on four threads. `time_cases`, `instructions` and `speed_costs` take cases as positional arguments. When a case starts with `-`, put the cases last, after `--`, as in `bpl-tests speed_costs -- '-.×m' '+/v'`. `bpl-tests NAME -h` lists a function's arguments.
32
34
 
33
35
  On each push, the `Test` workflow logs every native cost in its `test` job and every wasm cost in its `wasm` job. The speed test that writes them times the test-profile build that the budgets limit. `bpl --costs FILE` times the cases in a file in `speed.txt`'s format as the speed test does, and prints each cost with this machine's budget, without failing on a budget. The manual `Speed` workflow runs it on a `dist` build, the profile releases use, on CI's runner, beside its wasm timing. The `Release` workflow runs it on each binary it builds, on GitHub's runners. Their logs show what releases cost, for comparison with the `Test` workflow's. `logged_costs` reads all three workflows' logs. When you review a run, look for costs over their budgets and for costs that changed by more than 20%. Study a slowdown until you know its cause only when it appears in more than one CI run, or when two or more similar cases slow by similar amounts. Treat any other slowdown as normal variation.
34
36
 
@@ -116,7 +118,7 @@ User-facing language rules belong in `nbs/syntax.qmd`, `evaluation.qmd`, `number
116
118
 
117
119
  The lexer/parser records byte spans and structural syntax without evaluating expressions. `parse` distinguishes complete input, incomplete input and errors. It reads numbers under the thread's current settings, which `Session::parse` sets from the session first. `syntax_tree` supplies source tools with structural nodes and recovers invalid chunks as `Error` nodes. `highlight` shares the lexer.
118
120
 
119
- `symbols.rs` owns APL, simplified and traditional Hanzi spellings. Its rows also hold each glyph's names: a glyph name for the character, which is also its page's file name in `nbs/glyphs/`, and a name for each valence, or one name where both valences do the same thing. The glyph reference, named entry, help and Python's exported names all read them there. Parsing always accepts them together, canonicalizing token decisions while retaining original source and spans. Han characters are reserved outside strings and comments. The `notation` preference affects structured function/operator display, not stored source, serialization or structural APIs; help and editor metadata use the same spelling table.
121
+ `symbols.rs` owns APL, simplified and traditional Hanzi spellings. Its rows also hold each glyph's names: a glyph name for the character, which is also its page's file name in `nbs/glyphs/`, and a name for each valence, or one name where both valences do the same thing. The glyph reference, named entry, help and Python's exported names all read them there. `hanzi_aliases` enables Hanzi glyph spellings, canonicalizing token decisions while retaining original source and spans. Other Hanzi remain name characters. `_` quotes the next non-whitespace character into a name, including a glyph alias. The `notation` preference affects structured function/operator display, not stored source, serialization or structural APIs; help and editor metadata use the same spelling table.
120
122
 
121
123
  The binder resolves runtime categories right to left. It owns unfinished strands, trains and bound arguments; shared function nodes are immutable. Grammatical reduction produces application requests instead of calling functions. Primitive/operator rows own names, operand kinds, ranks, pervasion, axis behaviour and reduction identities. Change those rows instead of duplicating metadata in consumers. A non-extending primitive above its natural ranks runs through Rank; pervasive Each/Outer/Rank paths reuse whole-array kernels.
122
124
 
@@ -130,7 +132,7 @@ Dfns run statements in order and return the last statement's value. Final assign
130
132
 
131
133
  The binder records a dfn statement's steps on the statement's first evaluation (`eval/tree.rs`). Later evaluations replay that recording: they make the same calls in the same order, checking the category of each name, group and call result against the recorded one. Where a category differs, the binder carries on from the replay's state (`Binder::resumed`). Dot access, subscripts, joiners and runs that start with an operator rewrite a statement before the binder walks it (`Session::joined`, `Session::members`), and the recording keeps the rewritten nodes. The recording also keeps each fact about what names hold that the binding read (`tree::Fact`): whether a rewrite applies, and whether a run starts with an operator or ends in a dyadic one. A replay first checks those facts again, and evaluates the statement from its own nodes where one differs. A group or run whose leaves are all literals, primitives, operator glyphs or such groups, and which makes no call, records as the array or function it gave (`Recording::constant`), so a train like `(+/÷≢)` builds once. A replay reuses what an operator glyph, or one bound to a constant operand as in `⍤1`, derived from a constant operand when the statement recorded. The binder evaluates a statement every time when the statement assigns, selects, contains a run that ends in a dyadic operator, or needs more than 8 items on a stack. The parse tree depends on the evaluator, because each `syntax::Statement` holds its own recording. A change to a reduction that the binder records (a drop, a strand, an attach, a call, a derive, a bound right operand or a train) must change the replay too. `strand`, `attached`, `split_call`, `derived`, `bound_right`, `train` and `tail_call` in `eval/binder.rs` serve both. The `_ => rc.fail()` arm in `Binder::reduce` stops recording any statement with a reduction that the replay doesn't cover. The binder then evaluates that statement correctly every time.
132
134
 
133
- Tail calls reuse frames while preserving lexical dependencies. Handlers disable tail reuse. Native call depth is capped at 20,000; the browser cap is 380. A separate 20,000-frame limit bounds retained lexical frames. Late-bound name resolution stops at 128 levels. These are execution limits, not a sandbox against arbitrarily deep source, arrays or function graphs.
135
+ Tail calls reuse frames while preserving lexical dependencies. Handlers disable tail reuse. Native call depth is capped at 20,000; the browser cap is 380. Calls of primitives other than `⍎` don't count, because a primitive never calls back into BPL. They skip the depth, capture and stack bookkeeping, and on numbers a form that applies a kernel to each pair of items runs that kernel at once (`Primitive::scalar_call`). A separate 20,000-frame limit bounds retained lexical frames. Late-bound name resolution stops at 128 levels. These are execution limits, not a sandbox against arbitrarily deep source, arrays or function graphs.
134
136
 
135
137
  ## Values, layouts and assignment
136
138
 
@@ -172,7 +174,7 @@ Floats use IEEE NaN, infinity and signed zero. Comparison treats NaN as unequal;
172
174
 
173
175
  Under `•prefs ["kinds":"static"]`, a result's kind follows from its arguments' kinds alone, as `meta/kinds.md` describes. `Numeric` carries `kinds` and `int`. `pervasive::map` chooses a dyadic call's kind through `joined`, which applies rustymath's `DType::common` after `Numeric::kind`. Atoms promote as arrays do. Python's API makes its scalar arguments weak through `Value::weakened`. The loops keep the failed results that `keeps` names: floats' NaNs, and the wrapped integers of objects that report `WRAPS`. The kernel tables choose float `⌊ ⌈ ×` and wrapping negation from `run.numeric()`. `Stored::build_at` keeps complex results complex. `Primitive::number` gives every pervasive result on numbers, as well as each step of the fold of numbers, and `statically` adjusts it. `Number::parse` keeps complex literals and checks integer literals against the `int` width.
174
176
 
175
- Session settings live in one central place and are read from there, not passed through functions, except where a read is slow and on a hot path. That place is a per-thread variable that `Numeric::current` reads. `Session::evaluation` and `Session::parse` copy the session's `Numeric` into it when they start. `•prefs` updates both. Nothing resets it. A value read after its evaluation ends, by Python, the JSON worker, display or a Rust embedder, reads under its session's settings, unless another session has run on the thread since. Every frontend reads values on the thread that evaluated them. A `•prefs` call partway through a session changes the settings from then on, and a value made before it can read or compute under the new settings. A module that `•load` runs uses its loader's session and settings. Each call reads `Numeric::current` once where it starts: `pervasive::halves`, which every `pervasive` entry point goes through, `fusion::defers` and `defer`, `Domain::of`, the lexer and `Storage::item`'s complex items. Values derived from the settings within a call stay explicit arguments. `halves` passes 16-bit floats' widened settings to its inner call. The loop structs keep them because their closures run on rustymath's worker threads. A fused graph takes the current settings when it's built at forcing, for the same reason. `Number`'s tolerance methods and `Primitive::number` take them because they run once per item. The parser's leaves take a width marker's width, and `matches_within` takes `⍣∞`'s convergence tolerance. Imports build complex numbers with `Number::complex_in_session`: Python's `_Session.array` and the JSON protocol's `request`. JavaScript values hold no complex numbers.
177
+ Settings live once for the whole process, in `settings.rs`, and are read from there, not passed through functions, except where a read is slow and on a hot path. Each setting that calls and scalar operations read is an atomic: the numeric settings, the hanzi aliases, the `batch` pref, the fusion report flag and fusion's small sizes. The display settings sit behind one lock. `•prefs` writes them, the lexer writes a source's leading `•prefs` header as it reads it, and `settings::reset` restores the defaults, as `]clear` and the test harnesses do. Nothing copies, captures or restores a setting. A pending array computes under the settings in force when it computes, and a module that `•load` runs changes the settings for the whole process. Rustymath holds the thread count, the one setting that it reads itself, and `•prefs` writes it there. Each call reads the store once where it starts: `pervasive::halves`, which every `pervasive` entry point goes through, `fusion::defers` and `defer`, `Domain::of`, the lexer and `Storage::item`'s complex items. Values derived from the settings within a call stay explicit arguments. `halves` passes 16-bit floats' widened settings to its inner call. The loop structs keep them because their closures run on rustymath's worker threads. A fused graph reads the settings once when it's built at forcing, for the same reason. `Number`'s tolerance methods and `Primitive::number` take them because they run once per item. The parser's leaves take a width marker's width, and `matches_within` takes `⍣∞`'s convergence tolerance. Imports build complex numbers with `Number::complex_in_session`: Python's `_Session.array` and the JSON protocol's `request`. JavaScript values hold no complex numbers.
176
178
 
177
179
  Only f64 comparisons use the session tolerance, from 0 to `1E-14`. f32/f16 compare exactly except fixed-point convergence, which uses four ulps; f64 convergence uses `1E-14` independently of the preference. Index/count/Boolean/character-offset conversion uses `near_integer` with the fixed default tolerance, not the comparison preference. The tolerant types and objects come from rustymath. Keep independent inside/outside-tolerance tests with exact/mixed controls; don't use language comparison as its own oracle.
178
180
 
@@ -182,6 +184,8 @@ Only f64 comparisons use the session tolerance, from 0 to `1E-14`. f32/f16 compa
182
184
 
183
185
  Rustymath owns the mathematical algorithms. Basedpl owns pervasion, storage, numeric promotion, axes and language policy. Code whose inputs and outputs are only buffers, shapes and plain numbers belongs in rustymath, even when only basedpl calls it. Approximate matrix solve/pseudoinverse and decomposition use rustymath factorizations. On macOS, rustymath sends much of this work to Accelerate, as its DEV.md describes. No platform-specific adapter belongs here. The Cargo configuration, for Cargo's own builds, and `pyproject.toml`, for the wheels, both set the macOS deployment minimum to 15. Exact solve/pseudoinverse/determinant use rational field algorithms. Generic permanent and polynomial helpers also run at floating/complex field types. Singular/wide matrix division gives least-norm solutions. LU eligibility and SVD cutoffs are rustymath policy, not duplicated here.
184
186
 
187
+ Hash maps and sets come from `rustymath::hashing`, as rustymath's DEV.md describes. Use its `HashMap`, `HashSet` and `Hashing` rather than another hasher, so every lookup in both projects inlines its hash the same way.
188
+
185
189
  `•decompose`/`•decompose⁻¹` share domain reading and `Factor` dispatch, with options for kind, vectors and complete QR. Polynomial adapters choose compact evaluation or generic field operations; gradients differentiate coefficients before evaluating. Number-theory adapters supply cancellation checks and assemble result cells. Distribution constructors expose native density/CDF/quantile/sample functions. Compact continuous calls use slice objects. Discrete samples and finite discrete quantiles are exact integers.
186
190
 
187
191
  `•rand seed` makes a ChaCha8 stream behind a mutex (`distribution::Stream`), which every copy of its record shares. `¿` and a distribution's `sample` without a generator draw from the session's stream, which `•prefs ["seed":n]` reseeds. Draws take a stream's numbers in the order they run. The algorithm is fixed, but range/distribution sampler changes can change draws; the reference sequence detects that. Sampling from a generator record uses its roll function to recover the same stream.
@@ -202,13 +206,13 @@ Ordinary pervasive kernels also read pending copies through their maps. `fusion:
202
206
 
203
207
  `explain.rs` holds the events that `•explain` reports. One check in `Function::reported` serves both `•prefs ["fusion":$t]` and `•explain`: a call that computes a pending argument writes the pref's line and records a `forced` event. `Graph::explained` records a fused group where a graph runs, and where a fold reads through one. `Idiom::call` records each fast combination taken, by the name `Idiom::name` gives. `linear::scatter_add`, and the transpose of a gather that scatters a source's items, record each accumulation. `Selection::write_into`, where assignment and Under write, records each write that leaves a compact array mixed. Fusion runs graphs without a session, so events go to a sink on the evaluating thread, which holds them only while `•explain` runs. Outside it, `call` pays one branch on the session's flags. Each record node and pending array holds an `explain::Live` guard, which counts it for the thread that made it until it is dropped, on any thread. `•memory` reports those counts, and `Value::footprint` walks a value's allocations for its `bytes`.
204
208
 
205
- `derivative.rs` implements `∂`. A dual is a tag, a primal and a tangent: a `transform::Carrier`, held in `Value::Carried` for a number and in `Data::Carried` for an array, whose primal and tangent can be pending. A record of linear calls is the other kind of carrier. Routing (`transform::call` and `transform::route`) hands a call to the newest level among its arguments, as `Value::newest` finds it. It reads their outer layer, but a newer level inside an argument held in mixed storage wins, as an array of dual atoms beside an older dual shows. A call whose newest level is a `∂` call goes to `derivative::call`, which reads how to run it from the form's facts in `Primitive::info()` (`primitive::Facts`). It applies the partials table to pervasive forms and its own rule to `⌻`, and calls forms whose results carry no tangent on the primals. Structural glyphs, Under and selective assignment need no rules. Their own code moves each part of a carried array through the carrier's moves: `Carrier::view`, `Carrier::at`, `Carrier::copied`, and `transform::written` for writes, which a record answers through its ids. `Gather` copies a dual's primal and tangent together through `derivative::Join`. A glyph that copies its right argument through one plan, and a broadcast, copy a record tangent as one `Op::Copy` of the plan's `Steps` (`primitive::copied`, and `Form::Moves`'s `planned`). Its transpose reads through rustymath's `Steps::transposed`: the inverse map for a copy that reads each item at most once, and a correlation for windows that move by 1. A copy of a copy transposes in one read where the composed copy still transposes by reads (`linear::composed`). The record keeps the chain, because recognising windows needs each copy's own shape. A sum along a window's axis transposes as a sliding sum (`linear::slide`), and a spread axis as a sum along it. Windows that move by more than 1 transpose by rustymath's `signal::overlap_add`, which adds each window back where it read (`linear::strided_back`). Other copies, and copies of several sources, keep ids and scatter. `•explain` lists each scatter as an accumulation. In reverse mode, the rule for a `⌈` or `⌊` fold is a sum of the tangent times a mask of each lane's chosen item. Its transpose reads. Mix of a dual whose primal is nested mixes the primal and the tangent apart. `fold` and scans with `+`, `×`, `⌈` and `⌊`, `+.×` and outer products have rules, and kernels that read numbers directly leave active arguments to their general paths. Folds by primitives, products of primitives, `⌹`, `⊥` and stacks of matrices route through `transform::call` as operations (`primitive::Operation`), so their rules (`derivative::solve`, `decode`, `product_dual`, `determinant` and `fold_dual`) run on a `&Context` and call `Operation::call` for the products, folds and inverses that they need. Rank's routes for whole arguments send stacks that a level carries through `Pairing::Matrices`, so `⌹⍤2`, `+.×⍤2` and `-.×⍤2` take their stacked rules in one call, with the `batch` pref on or off. `transform::route` takes only what needs a `&mut Context`: attached rules, system functions, and folds and products by functions that aren't primitives. The rules for `⌹` and `-.×` keep the glyph's own result as the primal, so that a function computes the same values with or without `∂`. Their tangents and transposes multiply by `R`, the inverse that `numeric::matrix_inverse` takes from one factorization through rustymath's `linalg::inverse`. `regular_inverse` gives UNSUPPORTED where rustymath's regularity test finds the matrix singular. With only `B` active, `R` is `⌹A`, a pseudoinverse included. With one number in `x`, `f∂ x` runs `f` once with `x` seeded along it. With more, `linearized` pushes a record level just below its `∂` call's level, then runs `f` once with each part of `x` seeded with a record at that level, from `linear.rs`: a tangent whose items are never computed, which the same rules extend into a graph of linear calls. A call whose newest level is a record level records the linear map that its form's facts name (`linear::call`). `reverse` then reads the Jacobian from the record, by a transpose for each result item or a forward evaluation for each number of `x`, whichever are fewer. A function with a JVP rule that `f∂←g` attached calls the rule with `⍺` a dual of zeros whose tangent is the argument's, so in reverse mode the rule extends the record too (`derivative::attached`). A call of such a function with two arguments gives DOMAIN ERROR wherever `∂` needs a derivative through it (`derivative::two_arguments`). Code that reads a dual array's storage gets its items as dual atoms, which is correct at per-item speed. A rule packs an array that holds its level's duals, at any depth, into one dual before it splits the array (`derivative::packed`). A reader outside a call sees a value through `transform.rs`'s read point. `Value::observed`, which counts, positions, ranks, selectors, `≡` and guards' predicates use, reads a dual's primal. The integer readers of `Items` read carried items through it (`Value::observed_number`), so a count or position that `∂` carries reads its primal. It returns a `Result` whose error, `transform::Stop`, names the level that owns a batched run. A stop is `ErrorKind::Stop`, which no guard catches, even one that names it, and which a handler that catches every error lets pass (`ErrorKind::is_control`). Display reads through `Value::displayed`, because it never runs inside a batched run. `Value::computed`, which kernels use through `primitive::numeric`, gives UNSUPPORTED for a dual atom. Writes to bindings outside a `∂` call are recorded and stripped when it returns.
209
+ `derivative.rs` implements `∂`. A dual is a tag, a primal and a tangent: a `transform::Carrier`, held in `Value::Carried` for a number and in `Data::Carried` for an array, whose primal and tangent can be pending. A record of linear calls is the other kind of carrier. Routing (`transform::call`) hands a call to the newest level among its arguments, as `Value::newest` finds it. It reads their outer layer, but a newer level inside an argument held in mixed storage wins, as an array of dual atoms beside an older dual shows. A call whose newest level is a `∂` call goes to `derivative::call`, which reads how to run it from the form's facts in `Primitive::info()` (`primitive::Facts`). It applies the partials table to pervasive forms and its own rule to `⌻`, and calls forms whose results carry no tangent on the primals. Structural glyphs, Under and selective assignment need no rules. Their own code moves each part of a carried array through the carrier's moves: `Carrier::view`, `Carrier::at`, `Carrier::copied`, and `transform::written` for writes, which a record answers through its ids. `Gather` copies a dual's primal and tangent together through `derivative::Join`. A glyph that copies its right argument through one plan, and a broadcast, copy a record tangent as one `Op::Copy` of the plan's `Steps` (`primitive::copied`, and `Form::Moves`'s `planned`). Its transpose reads through rustymath's `Steps::transposed`: the inverse map for a copy that reads each item at most once, and a correlation for windows that move by 1. A copy of a copy transposes in one read where the composed copy still transposes by reads (`linear::composed`). The record keeps the chain, because recognising windows needs each copy's own shape. A sum along a window's axis transposes as a sliding sum (`linear::slide`), and a spread axis as a sum along it. Windows that move by more than 1 transpose by rustymath's `signal::overlap_add`, which adds each window back where it read (`linear::strided_back`). Other copies, and copies of several sources, keep ids and scatter. `•explain` lists each scatter as an accumulation. In reverse mode, the rule for a `⌈` or `⌊` fold is a sum of the tangent times a mask of each lane's chosen item. Its transpose reads. Mix of a dual whose primal is nested mixes the primal and the tangent apart. `fold` and scans with `+`, `×`, `⌈` and `⌊`, `+.×` and outer products have rules, and kernels that read numbers directly leave active arguments to their general paths. Folds by primitives, products of primitives, `⌹`, `⊥` and stacks of matrices route through `transform::call` as operations (`primitive::Operation`), so their rules (`derivative::solve`, `decode`, `product_dual`, `determinant` and `fold_dual`) run on a `&Context` and call `Operation::call` for the products, folds and inverses that they need. Rank's routes for whole arguments send stacks that a level carries through `Pairing::Matrices`, so `⌹⍤2`, `+.×⍤2` and `-.×⍤2` take their stacked rules in one call, with the `batch` pref on or off. Attached rules, system functions, and folds and products by functions that aren't primitives route through the same `transform::call`, as `transform::Op`'s other variants. The rules for `⌹` and `-.×` keep the glyph's own result as the primal, so that a function computes the same values with or without `∂`. Their tangents and transposes multiply by `R`, the inverse that `numeric::matrix_inverse` takes from one factorization through rustymath's `linalg::inverse`. `regular_inverse` gives UNSUPPORTED where rustymath's regularity test finds the matrix singular. With only `B` active, `R` is `⌹A`, a pseudoinverse included. With one number in `x`, `f∂ x` runs `f` once with `x` seeded along it. With more, `linearized` pushes a record level just below its `∂` call's level, then runs `f` once with each part of `x` seeded with a record at that level, from `linear.rs`: a tangent whose items are never computed, which the same rules extend into a graph of linear calls. A call whose newest level is a record level records the linear map that its form's facts name (`linear::call`). `reverse` then reads the Jacobian from the record, by a transpose for each result item or a forward evaluation for each number of `x`, whichever are fewer. A function with a JVP rule that `f∂←g` attached calls the rule with `⍺` a dual of zeros whose tangent is the argument's, so in reverse mode the rule extends the record too (`derivative::attached`). A call of such a function with two arguments gives DOMAIN ERROR wherever `∂` needs a derivative through it (`derivative::two_arguments`). Code that reads a dual array's storage gets its items as dual atoms, which is correct at per-item speed. A rule packs an array that holds its level's duals, at any depth, into one dual before it splits the array (`derivative::packed`). A reader outside a call sees a value through `transform.rs`'s read point. `Value::observed`, which counts, positions, ranks, selectors, `≡` and guards' predicates use, reads a dual's primal. The integer readers of `Items` read carried items through it (`Value::observed_number`), so a count or position that `∂` carries reads its primal. It returns a `Result` whose error, `transform::Stop`, names the level that owns a batched run. A stop is `ErrorKind::Stop`, which no guard catches, even one that names it, and which a handler that catches every error lets pass (`ErrorKind::is_control`). Display reads through `Value::displayed`, because it never runs inside a batched run. `Value::computed`, which kernels use through `primitive::numeric`, gives UNSUPPORTED for a dual atom. Writes to bindings outside a `∂` call are recorded and stripped when it returns.
206
210
 
207
- `batch.rs` makes a map's batched call. `batch::tried`, which `each_pair` calls, begins a batched level for the run (`transform::Kind::Batched`), wraps each argument that has a frame in a `Batch` carrier at that level, calls the operand once, and ends the level. Each map first lays its arguments over its frame through its own agreement, the pairing that its calls on each cell read (`batch::Arguments::laid` and `agreement::laid_cells`). `each_pair` makes no batched call for one cell of atoms, which runs faster without one. Routing hands each call whose newest level is the run's to `batch::call`, for a primitive or an operation that primitives name, such as a fold by a primitive or `+.×`, or to `batch::route`, for an operation by a dfn. Both leave `⍕` and system functions to their own code, whose effect check decides for every argument (`Levels::effect`). `batch::call` runs the call on the whole arguments by Rank's routes: `eval::whole_cells` through `batch::whole_call`, and `eval::folded_cells` for a fold. A primitive therefore batches wherever Rank runs it on whole arguments. A fold or scan that `folded_cells` doesn't cover, such as one by a dfn, runs the fold's own loop over the batch's items. Each stage is then one call, on item `j` of every cell (`Batch::at`). `fold_array` and `primitive_fold` join a result that holds stage batches into one batch (`joined`). Every fold and scan route decides its structural cases, such as a unit, empty lanes and the result's shape, through `FoldPlan`, and ends in `folded`, which alone gives the result its layout, fused folds included. A fold or scan by any function other than a primitive, over more than one lane, also tries a batched run of its own: `operators::by_lanes` moves the fold axis last and runs the derived fold over the lanes through `batch::tried`. `operators::by_triples` does the same for `f.g` where `g` isn't a primitive: one batched call of `g` on a frame of rows by contraction by columns, then the fold by `f` along the contraction, for each chunk of rows whose triples hold at most `batch::CHUNK` items (`operators::by_rows`, which products of primitives share). Each runs its usual loop from the start where its try gives `None`. A fold keeps its stops on its operand's `Definition` (`Function::remembers`). `batch::tries` holds the conditions for any try. A call that no route covers stops the run (`transform::Stop`). A call whose constants with axes, repeated over the frame, would hold more than 4 times the items of its arguments and more than `batch::CHUNK` items, 2²¹, stops the run with the cells of a chunk whose share holds at most `CHUNK` items (`oversized`, `Stop::chunk`). `tried` then runs the operand once on each chunk of that many cells (`batch::chunked`), each as a batched level on a frame of one axis, and joins the chunks' results as the run over cells assembles its cells' results. A chunk that stops for too many items again starts the chunks over with its own smaller chunk. Where one cell's share alone passes `CHUNK`, the map calls its operand once for each cell. Code that must run once for each cell asks the levels first (`Levels::effect`): output, input, `⍕` of a carried value and system functions other than random draws (`Effect::Acts`), a guard or a call on prototypes that would catch an error (`Effect::Catches`), and a write to a binding outside the map's frames (`Effect::Writes`, through `Levels::record_write`). A read through `Value::observed`, as a count or a position makes, stops the run too. A guard whose predicate is a batch of the run splits the run instead (`Session::guard` through `operators::guard`). `batch::truths` gives each cell's Boolean, and each side runs once, as a guard case on its own cells (`Levels::case`), through the `Cells` that `⍚` uses. Each batched binding in the frames that the run started is read at the side's cells (`Session::restricted`, through `batch::read_cells` and `operators::cells_at`), and `Cells::assembled` joins the sides' results. During a case, the run's frame is the case's cells, a random draw draws for the case's cells, and a write to an enclosing frame stops the run. A guard of a dfn that already splits the cells in another frame stops the run as a recursive call (`Cause::Recursion`), and sides whose cells differ in layout or kind stop it as a call with no rule. Each stop carries its cause (`transform::Cause`), which says how long a dfn operand remembers it (`Cause::kept`). An effect, a write, an observing read or a recursive call lasts for every later call. A call that no route covers lasts while later calls repeat the arguments' kinds and cell shapes, and the memory guard lasts while they also repeat the frame's shape. A caught error never lasts, because whether an error arises depends on the cells' values. The dfn's `Definition` holds what it remembers (`Definition::remember`): `ALWAYS`, or a signature of the arguments (`batch::signature`), each holding the stop's cause (`batch::holding`). A later try that it covers falls back without calling the operand, with an `"an earlier stop"` event that names the cause. A stop's own `fallbacks` event names its cause (`Cause::reason`), and the glyph of a primitive whose call no rule covers (`Stop::refusing`). Code with no rule for batches that reads a batch's items gets item carriers, item i of every cell, and records an `itemwise` row, route `"batched items"`. `explain::itemwise` is the one helper for routes that handle items one at a time, and the innermost call claims its counts (`Function::reported`), as `forced` does. A kernel that then reads a number meets the stop that `Carrier::computed` gives a batch. A missed reader therefore costs speed or a fallback, never a wrong result. A batched run can also start inside a `∂` call. The run's level is newer than the `∂` tag, so the batch rules take each call first, and their calls on whole arrays reach the derivative rules. A batch's whole can then carry a dual, whose kind batch checks read through `Value::template_dtype`. Stacks of matrices whose wholes carry a dual take the derivative rules through `Pairing::Matrices` (`eval::whole_cells`), because the stacked kernels read compact storage. A `∂` call inside the run differentiates with respect to batches of atoms or of arrays. `derivative::numbers` counts a cell's numbers from the batch's template, every cell shares each direction's seed, and the Jacobian joins into one batch (`batch::joined`). A move with no plan on a dual whose primal is a batch runs on the primal and the tangent apart (`derivative::apart`). Adjoints that a transpose adds into a batch add as one sum on its whole (`batch::scatter_add`). An attached rule runs on the whole batch at its argument's `∂` tag (`batch::route`), and `batch::split_whole` and `batch::dual_of_wholes` keep the newest level outermost. A roll draws once, on its argument laid over the frame (`distribution::drawn_items`), and deals and samples draw for each cell in turn (`distribution::each_cell`), all from one stream in cell order. Where each cell draws once, seeded draws match a run cell by cell, except under a guard that splits the cells, where each side draws for its own cells in turn. A try that falls back puts back the state of each generator it drew from (`distribution::settle`). The map's result must be a batch at its level, a strand of batches whose kinds join (`joined`), or an atom or compact array with no carrier, as every cell's result. Any other result falls back. A pervasive call stops where its result's kind differs from the kind that one route gives every item (`pervasive::expected`). Each cell then keeps the kind that a run cell by cell gives it. `reference::check` runs each reference case with the `batch` pref off, then on, then on under fusion's small sizes (`fusion::Sizes::SMALL`), and compares the storage kinds of the later runs' values with the first's.
211
+ `batch.rs` makes a map's batched call. `batch::tried`, which `each_pair` calls, begins a batched level for the run (`transform::Kind::Batched`), wraps each argument that has a frame in a `Batch` carrier at that level, calls the operand once, and ends the level. Each map first lays its arguments over its frame through its own agreement, the pairing that its calls on each cell read (`batch::Arguments::laid` and `agreement::laid_cells`). `each_pair` makes no batched call for one cell of atoms, which runs faster without one. Routing hands each call whose newest level is the run's to `batch::call`: a primitive, an operation that primitives name, such as a fold by a primitive or `+.×`, or an operation by a dfn. It leaves `⍕` and system functions to their own code, whose effect check decides for every argument (`Levels::effect`). `batch::call` runs the call on the whole arguments by Rank's routes: `eval::whole_cells` through `batch::whole_call`, and `eval::folded_cells` for a fold. A primitive therefore batches wherever Rank runs it on whole arguments. A fold or scan that `folded_cells` doesn't cover, such as one by a dfn, runs the fold's own loop over the batch's items. Each stage is then one call, on item `j` of every cell (`Batch::at`). `fold_array` and `primitive_fold` join a result that holds stage batches into one batch (`joined`). Every fold and scan route decides its structural cases, such as a unit, empty lanes and the result's shape, through `FoldPlan`, and ends in `folded`, which alone gives the result its layout, fused folds included. A fold or scan by any function other than a primitive, over more than one lane, also tries a batched run of its own: `operators::by_lanes` moves the fold axis last and runs the derived fold over the lanes through `batch::tried`. `operators::by_triples` does the same for `f.g` where `g` isn't a primitive: one batched call of `g` on a frame of rows by contraction by columns, then the fold by `f` along the contraction, for each chunk of rows whose triples hold at most `batch::CHUNK` items (`operators::by_rows`, which products of primitives share). Each runs its usual loop from the start where its try gives `None`. A fold keeps its stops on its operand's `Definition` (`Function::remembers`). `batch::tries` holds the conditions for any try. A call that no route covers stops the run (`transform::Stop`). A call whose constants with axes, repeated over the frame, would hold more than 4 times the items of its arguments and more than `batch::CHUNK` items, 2²¹, stops the run with the cells of a chunk whose share holds at most `CHUNK` items (`oversized`, `Stop::chunk`). `tried` then runs the operand once on each chunk of that many cells (`batch::chunked`), each as a batched level on a frame of one axis, and joins the chunks' results as the run over cells assembles its cells' results. A chunk that stops for too many items again starts the chunks over with its own smaller chunk. Where one cell's share alone passes `CHUNK`, the map calls its operand once for each cell. Code that must run once for each cell asks the levels first (`Levels::effect`): output, input, `⍕` of a carried value and system functions other than random draws (`Effect::Acts`), a guard or a call on prototypes that would catch an error (`Effect::Catches`), and a write to a binding outside the map's frames (`Effect::Writes`, through `Levels::record_write`). A read through `Value::observed`, as a count or a position makes, stops the run too. A guard whose predicate is a batch of the run splits the run instead (`Session::guard` through `operators::guard`). `batch::truths` gives each cell's Boolean, and each side runs once, as a guard case on its own cells (`Levels::case`), through the `Cells` that `⍚` uses. Each batched binding in the frames that the run started is read at the side's cells (`Session::restricted`, through `batch::read_cells` and `operators::cells_at`), and `Cells::assembled` joins the sides' results. During a case, the run's frame is the case's cells, a random draw draws for the case's cells, and a write to an enclosing frame stops the run. A guard of a dfn that already splits the cells in another frame stops the run as a recursive call (`Cause::Recursion`), and sides whose cells differ in layout or kind stop it as a call with no rule. Each stop carries its cause (`transform::Cause`), which says how long a dfn operand remembers it (`Cause::kept`). An effect, a write, an observing read or a recursive call lasts for every later call. A call that no route covers lasts while later calls repeat the arguments' kinds and cell shapes, and the memory guard lasts while they also repeat the frame's shape. A caught error never lasts, because whether an error arises depends on the cells' values. The dfn's `Definition` holds what it remembers (`Definition::remember`): `ALWAYS`, or a signature of the arguments (`batch::signature`), each holding the stop's cause (`batch::holding`). A later try that it covers falls back without calling the operand, with an `"an earlier stop"` event that names the cause. A stop's own `fallbacks` event names its cause (`Cause::reason`), and the glyph of a primitive whose call no rule covers (`Stop::refusing`). Code with no rule for batches that reads a batch's items gets item carriers, item i of every cell, and records an `itemwise` row, route `"batched items"`. `explain::itemwise` is the one helper for routes that handle items one at a time, and the innermost call claims its counts (`Function::reported`), as `forced` does. A kernel that then reads a number meets the stop that `Carrier::computed` gives a batch. A missed reader therefore costs speed or a fallback, never a wrong result. A batched run can also start inside a `∂` call. The run's level is newer than the `∂` tag, so the batch rules take each call first, and their calls on whole arrays reach the derivative rules. A batch's whole can then carry a dual, whose kind batch checks read through `Value::template_dtype`. Stacks of matrices whose wholes carry a dual take the derivative rules through `Pairing::Matrices` (`eval::whole_cells`), because the stacked kernels read compact storage. A `∂` call inside the run differentiates with respect to batches of atoms or of arrays. `derivative::numbers` counts a cell's numbers from the batch's template, every cell shares each direction's seed, and the Jacobian joins into one batch (`batch::joined`). A move with no plan on a dual whose primal is a batch runs on the primal and the tangent apart (`derivative::apart`). Adjoints that a transpose adds into a batch add as one sum on its whole (`batch::scatter_add`). An attached rule runs on the whole batch at its argument's `∂` tag (`batch::call`), and `batch::split_whole` and `batch::dual_of_wholes` keep the newest level outermost. A roll draws once, on its argument laid over the frame (`distribution::drawn_items`), and deals and samples draw for each cell in turn (`distribution::each_cell`), all from one stream in cell order. Where each cell draws once, seeded draws match a run cell by cell, except under a guard that splits the cells, where each side draws for its own cells in turn. A try that falls back puts back the state of each generator it drew from (`distribution::settle`). The map's result must be a batch at its level, a strand of batches whose kinds join (`joined`), or an atom or compact array with no carrier, as every cell's result. Any other result falls back. A pervasive call stops where its result's kind differs from the kind that one route gives every item (`pervasive::expected`). Each cell then keeps the kind that a run cell by cell gives it. `reference::check` runs each reference case with the `batch` pref off, then on, then on under fusion's small sizes (`fusion::Sizes::SMALL`), and compares the storage kinds of the later runs' values with the first's.
208
212
 
209
213
  Rustymath owns numeric folds, scans, adjacent pairs, grouped reductions and integer bounds. Basedpl selects kernels, tolerance, seeds, storage widths and exact fallbacks. Folds by algebraic float operations can regroup. Contiguous subtraction/division folds use `Alternating`; quotients fall back to item-by-item folding if their products leave the normal range. Boolean scans compose truth-table maps; comparison scans compute both possible totals in bulk and use `reduce::chosen`. Seeds, axis lanes and scalar fallback preserve the language's accumulation direction. Generic reductions stay right-associated and preserve operand call order/effects. Monadic `f.g` is the exception: it memoizes each minor's expansion, and a cached minor does not repeat operand calls or their effects. Determinant/permanent fast paths use the appropriate rustymath backend.
210
214
 
211
- The automatic Rayon scheduler serves rustymath elementwise `many` and `pairs`, broadcasts through `agreement::blocks`, folds through `reduce::along`, fused graphs and matrix products. Scans don't split. Decompositions split in the products of their blocked updates, the passes of their Hermitian and bidiagonal reductions, and their divide-and-conquer merges. `rank` sends dyadic `+.×` and `⌹`, monadic `⌹` and `-.×`, and `•decompose` over the 2-cells of an unkeyed stack with compact storage to `primitive::stacked` and `stacked_decompositions`. They run each cell through the rustymath function it uses alone. A pervasive operand, or Rank nested down to one, runs as one call: each argument gets length-1 axes after each level's frame, so leading-axis agreement pairs frames with frames and cells with cells. Arguments with axis names still go cell by cell. Rustymath's `parallel::stack_with` splits whole cells across threads in rounds, with `check_now` between rounds. A caller whose checks run far apart, such as a round or a rustymath `_with` callback, calls `check_now`, because `Context::check` reads the clock only on every 64th call. The scheduler adapts to call cost, uses `RAYON_NUM_THREADS` by default and accepts current-thread overrides through `parallel::set_threads` (0 default, 1 serial). `Session::evaluation` applies a session's `•prefs ["threads":n]` to each of its evaluations, then restores the thread's own setting. A session that never sets it keeps the evaluating thread's setting, such as the timing harness's one thread. Nested Rayon work does not split again; wasm is serial. A fused graph splits in pieces of whole blocks: an elementwise graph through `parallel::extended`, and a folded one through `reduce::fold_pieces`. On one thread an elementwise graph appends straight to its result, because copying each block into a piece's slots cost up to 1.2 copies there. Small converted chunks limit the work available to the scheduler. Don't infer multicore execution from a large array alone.
215
+ The automatic Rayon scheduler serves rustymath elementwise `many` and `pairs`, broadcasts through `agreement::blocks`, folds through `reduce::along`, fused graphs and matrix products. Scans don't split. Decompositions split in the products of their blocked updates, the passes of their Hermitian and bidiagonal reductions, and their divide-and-conquer merges. `rank` sends dyadic `+.×` and `⌹`, monadic `⌹` and `-.×`, and `•decompose` over the 2-cells of an unkeyed stack with compact storage to `primitive::stacked` and `stacked_decompositions`. They run each cell through the rustymath function it uses alone. A pervasive operand, or Rank nested down to one, runs as one call: each argument gets length-1 axes after each level's frame, so leading-axis agreement pairs frames with frames and cells with cells. Arguments with axis names still go cell by cell. Rustymath's `parallel::stack_with` splits whole cells across threads in rounds, with `check_now` between rounds. A caller whose checks run far apart, such as a round or a rustymath `_with` callback, calls `check_now`, because `Context::check` reads the clock only on every 64th call. The scheduler adapts to call cost, uses `RAYON_NUM_THREADS` by default and accepts one override for the whole process through `parallel::set_threads` (0 default, 1 serial), which `•prefs ["threads":n]` writes directly. The timing harness sets one thread after each reset of the settings. Nested Rayon work does not split again; wasm is serial. A fused graph splits in pieces of whole blocks: an elementwise graph through `parallel::extended`, and a folded one through `reduce::fold_pieces`. On one thread an elementwise graph appends straight to its result, because copying each block into a piece's slots cost up to 1.2 copies there. Small converted chunks limit the work available to the scheduler. Don't infer multicore execution from a large array alone.
212
216
 
213
217
  Packed numeric, Boolean and equality-count inner products use `rustymath::linalg`. Other native pairs use its bounded `inner_with` runner and `reduce::right_fold`, carrying the right tail across blocks. Basedpl supplies its primitive kernels, tolerance and exact-widening fallback. Integer calls use `Inner::checked` before relying on an exact compact result. `pervasive::inner` takes each operand's `Orientation`. Its float and complex products read a transposed operand in place, as reverse mode's `product_transpose` needs. A float `+.×` whose operand is a pending copy, or a view of one, hands rustymath's `Inner::inner_mapped` the copy's source and map (`fusion::source`, `pervasive::mapped_product`). Rustymath gives gemm an operand that its map reads at strides, such as a transpose, where it lies (`Mapped::matrix`). It reads any other copy a block of rows at a time, except in a product with one column, where the copy's rows are adjacent in storage, as for a vector or a single-channel image. It then adds each column of the copy where it lies (`linalg::by_columns`). Neither builds the copy. A copy that a name holds is read again for each product rather than cached. Reverse mode transposes a product whose operand is windows that move by 1 as one product: the windows of the zero-padded cotangent with the kernel reversed (`linear::convolved_back`, rustymath's `signal::correlation`). Structural gather/compress and interval index also reuse rustymath. Measure changes to generic or backend code in both projects. The callers' codegen and layout decide costs that a kernel measured alone misses.
214
218
 
@@ -216,7 +220,7 @@ Packed numeric, Boolean and equality-count inner products use `rustymath::linalg
216
220
 
217
221
  `eval_with`/`call_with` install `EvalOptions`. Echo defaults to true; disabling it suppresses implicit display, not explicit output or display commands. Output is ordered `Output { kind, data }` MIME bundles. An optional sink receives events as produced; otherwise the evaluation retains them. Values, functions, operators, outputs and errors remain separate results.
218
222
 
219
- `Context` carries source and session. Checks at interpreter boundaries and long loops count down before reading clocks/flags or calling the poll hook. Individual BigInt operations and bounded native kernels are not preempted. Native functions receive `&Context`; evaluator functions use `&mut Context`. An optional `Input` supplies `⎕` and `•nget "-"`; without one they raise IO. Python uses cooperative cancellation. The process worker can kill an unresponsive process after a grace period, losing its state; requests are never replayed.
223
+ `Context` carries source and session. Checks at interpreter boundaries and long loops count down before reading clocks/flags or calling the poll hook. Individual BigInt operations and bounded native kernels are not preempted. Every function receives `&Context`, which holds `&Session`. The session's state sits in `Cell`s and `RefCell`s whose methods hand out owned values, so no caller holds a borrow of it while a dfn evaluates (`meta/session.md`). An optional `Input` supplies `⎕` and `•nget "-"`; without one they raise IO. Python uses cooperative cancellation. The process worker can kill an unresponsive process after a grace period, losing its state; requests are never replayed.
220
224
 
221
225
  `Session::call` resolves and calls a function expression on existing arrays without temporary argument bindings. Retained functions use `call_function_with`. Error objects retain source and byte spans, with Unicode-width display diagnostics. Python translates spans to character offsets; process JSON keeps bytes. Native function/operator handles cross the in-process Python boundary, not process JSON.
222
226
 
@@ -266,9 +270,9 @@ CSV columns, JSON arrays and Python lists share `data::imported`: a non-fill fin
266
270
 
267
271
  ## Tests and reference data
268
272
 
269
- `tests/core.rs` checks public storage/layout/API behaviour, ownership, parser diagnostics and recovery. Use `equiv_in!` for session workflows and `fails_in` for errors; expected expressions run in fresh sessions. Keep constructors for representation/prototype/buffer checks. Self-contained language cases belong in `tests/reference/core.bpl`. `cli/tests/cli.rs` and Python's pseudo-terminal tests exercise the installed process/editor boundary.
273
+ `tests/core.rs` checks public storage/layout/API behaviour, ownership, parser diagnostics and recovery. Use `equiv_in!` for session workflows and `fails_in` for errors; each expected expression runs in a fresh session after its code, under the settings that the code leaves. `tests/core.rs` never changes settings. The settings are one store for the whole process, so the checks that change them live in `tests/settings.rs`, which runs them in turn in one test, each from the defaults. Both binaries share the helpers in `tests/common/mod.rs`. Keep constructors for representation/prototype/buffer checks. Self-contained language cases belong in `tests/reference/core.bpl`. `cli/tests/cli.rs` and Python's pseudo-terminal tests exercise the installed process/editor boundary.
270
274
 
271
- `reference.rs` serves Rust tests and worker requests. Every reference case uses a fresh session; documentation examples share a session within each BPL code block. `.bpl` files define active coverage. Captured foreign expectations have no exactness; local expectations compare exactness and structural values independently. A local expectation also fixes where storage is mixed: the result must be held in mixed storage exactly where the expectation is, at each level of nesting (`kind_difference`), unless the case's header carries `mixed`. Pending gaps belong in inventory JSONL, not passing error tests. See `tests/reference/README.md` for format and review/activation workflow. `python/basedpl/reference.py`, `bpltests.py` and `scripts/reference.py` own import, capture, inventory and worker checks. `lib/*.bpl` are readable dfn examples; modules import other library files with private relative names.
275
+ `reference.rs` serves Rust tests and worker requests. Every reference case uses a fresh session; documentation examples share a session within each BPL code block, which starts from the default settings. A reference file's leading `•prefs` line sets the settings of all its cases. Each case runs three times, with the `batch` pref off, then on, then on with fusion's small sizes, and each run starts from the defaults and the file's header. The cases of a file run in parallel, one run at a time. A case whose code calls `•prefs`, such as a seeded draw, carries `serial` and runs alone after them, and the harness rejects a `•prefs` call in a case without it. `batched` leaves out the run with the `batch` pref off, and `unfused` the run with the small sizes. Each expectation evaluates after its code, under the settings that the code leaves. `.bpl` files define active coverage. Captured foreign expectations have no exactness; local expectations compare exactness and structural values independently. A local expectation also fixes where storage is mixed: the result must be held in mixed storage exactly where the expectation is, at each level of nesting (`kind_difference`), unless the case's header carries `mixed`. Pending gaps belong in inventory JSONL, not passing error tests. See `tests/reference/README.md` for format and review/activation workflow. `python/basedpl/reference.py`, `bpltests.py` and `scripts/reference.py` own import, capture, inventory and worker checks. `lib/*.bpl` are readable dfn examples; modules import other library files with private relative names.
272
276
 
273
277
  `tests/scaling.rs` measures time/allocation growth and result-size allocation budgets. `tests/speed.rs` reads native/browser budgets from `speed.txt` through `timing.rs`; the worker and Python measurement tools reuse it. `tests/units.rs` reads existing incremental object files and checks unit size without building. Python tests cover conversion/cancellation/frontend behaviour, not a second Rust semantic suite. Combine related checks into readable tests.
274
278
 
@@ -289,7 +293,7 @@ Quarto renders saved outputs. `bpl-nb --save` updates notebook outputs without c
289
293
 
290
294
  `basedpl.editors.write()` generates syntax grammars/highlighters, editor templates, keyboard sources/bundles and glyph metadata from shared Rust symbols and keyboard data. It also writes JetBrains assets and Windows `editors/windows/layout.h`. After a Rust change, run `python -m basedpl.editors` from the shell, because a running kernel keeps its old extension. `layout.json` owns composed input; captured `keyboards.json` supports generation without macOS. `basedpl.keyboards.capture()` refreshes native data when needed, and `keyboards.write()` generates regional macOS bundles/maps. Regenerate keyboard sources through these functions, not one-off kernel code. See `editors/jetbrains/README.md`, `editors/windows/README.md` and `scripts/install-macos.sh` for target-specific work. Rebuild the common icon only when its design changes.
291
295
 
292
- `nbs/bpl.xml`, the APL/BQN grammars and vim rules share generated glyph classes. TextMate exports feed Monaco/Shiki. `fonts.css` owns the BPL/APL font choices; rerun affected magics after changing them. `tests/highlighting.mjs`, `input.mjs`, keylayout/Windows tests and glyph-page checks cover their respective generated interfaces. All artifact generation belongs in repository functions/scripts, not ad hoc kernel transformations.
296
+ `nbs/bpl.xml`, the APL/BQN grammars and vim rules share generated glyph classes. `hpl.xml` includes BPL and adds Hanzi aliases from the same symbol table. Use `hpl` fences for Hanzi highlighting, `bpl` for Hanzi names. For Hanzi notebooks, set `kernelspec.language` to `hpl` and keep `kernelspec.name` as `bpl`. These labels do not enable runtime Hanzi aliases. TextMate exports feed Monaco/Shiki. `fonts.css` owns the BPL/APL font choices; rerun affected magics after changing them. `tests/highlighting.mjs`, `input.mjs`, keylayout/Windows tests and glyph-page checks cover their respective generated interfaces. All artifact generation belongs in repository functions/scripts, not ad hoc kernel transformations.
293
297
 
294
298
  ## Release
295
299
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basedpl
3
- Version: 0.1.62
3
+ Version: 0.1.63
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Requires-Dist: fastcore
@@ -0,0 +1,109 @@
1
+ {
2
+ "name": "bpl",
3
+ "displayName": "BPL",
4
+ "scopeName": "source.bpl",
5
+ "fileTypes": [
6
+ "bpl"
7
+ ],
8
+ "patterns": [
9
+ {
10
+ "begin": "[⍝]",
11
+ "beginCaptures": {
12
+ "0": {
13
+ "name": "comment.line.bpl"
14
+ }
15
+ },
16
+ "end": "$",
17
+ "contentName": "comment.line.bpl",
18
+ "patterns": [],
19
+ "applyEndPatternLast": true
20
+ },
21
+ {
22
+ "begin": "\"",
23
+ "beginCaptures": {
24
+ "0": {
25
+ "name": "string.quoted.double.bpl"
26
+ }
27
+ },
28
+ "end": "\"|$",
29
+ "contentName": "string.quoted.double.bpl",
30
+ "patterns": [
31
+ {
32
+ "match": "\"\"",
33
+ "name": "string.quoted.double.bpl"
34
+ }
35
+ ],
36
+ "applyEndPatternLast": true,
37
+ "endCaptures": {
38
+ "0": {
39
+ "name": "string.quoted.double.bpl"
40
+ }
41
+ }
42
+ },
43
+ {
44
+ "match": "'.?'",
45
+ "name": "string.quoted.single.bpl"
46
+ },
47
+ {
48
+ "match": "(?:_\\d+|_\\S|_|[^\\s\\p{Cc}0-9←⎕•⍺⍵⍶⍹∇⍢⍝⋄\\?¯∞⍬\\+\\-×÷⌈⌊\\|\\*⍟○π√!∧∨⊼⊽\\~=≠<≤>≥⍳↦:⍴≢≡,⍪⊂⊃⊆∊∪∩⍋⍒↑↓⌽⊖⍉⊤⊥⍎⍕⌷⌹\\#↕⍭⨸⌻⍸⍷⊢⊣¿¨ᵇ⍨↣⍤∘⍠⍥↢\\.⊗⌸⍣⇄⊘@∂⍚⌺/⌿\\\\⍀⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ₀₁₂₃₄₅₆₇₈₉₋\\(\\)\\[\\]\\{\\}'\";\\$_ₑⱼᵣ])+",
49
+ "name": "variable.other.bpl"
50
+ },
51
+ {
52
+ "match": "[•][A-Za-z_∆⍙][A-Za-z0-9_∆⍙]*",
53
+ "name": "support.function.system.bpl"
54
+ },
55
+ {
56
+ "match": "[¯]?[∞]|[¯]?(\\d+([.]\\d+)?|[.]\\d+)([eEₑ][¯]?\\d+)?([jJⱼ][¯]?(\\d+([.]\\d+)?|[.]\\d+)([eEₑ][¯]?\\d+)?|ₓ|[rᵣ][¯]?\\d+)?|[ₑⱼᵣ]",
57
+ "name": "constant.numeric.bpl"
58
+ },
59
+ {
60
+ "match": "[⍬]ₓ?",
61
+ "name": "constant.numeric.bpl"
62
+ },
63
+ {
64
+ "match": "\\$[tfn]",
65
+ "name": "constant.numeric.bpl"
66
+ },
67
+ {
68
+ "match": "\\$[ad]",
69
+ "name": "string.quoted.double.bpl"
70
+ },
71
+ {
72
+ "begin": "[\\])](?=ₓ)",
73
+ "beginCaptures": {
74
+ "0": {
75
+ "name": "source.bpl"
76
+ }
77
+ },
78
+ "end": "[ₓ]|$",
79
+ "contentName": "constant.numeric.bpl",
80
+ "patterns": [],
81
+ "applyEndPatternLast": true,
82
+ "endCaptures": {
83
+ "0": {
84
+ "name": "constant.numeric.bpl"
85
+ }
86
+ }
87
+ },
88
+ {
89
+ "match": "[\\+\\-×÷⌈⌊\\|\\*⍟○π√!∧∨⊼⊽\\~=≠<≤>≥⍳↦:⍴≢≡,⍪⊂⊃⊆∊∪∩⍋⍒↑↓⌽⊖⍉⊤⊥⍎⍕⌷⌹\\#↕⍭⨸⌻⍸⍷⊢⊣¿]",
90
+ "name": "support.function.bpl"
91
+ },
92
+ {
93
+ "match": "[¨ᵇ⍨⊗⌸⇄∂/⌿\\\\⍀⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ]",
94
+ "name": "keyword.operator.monadic.bpl"
95
+ },
96
+ {
97
+ "match": "[↣⍤∘⍠⍥↢\\.⍣⊘@⍚⌺]",
98
+ "name": "keyword.operator.dyadic.bpl"
99
+ },
100
+ {
101
+ "match": "[⍺⍵⍶⍹∇⍢]",
102
+ "name": "variable.parameter.bpl"
103
+ },
104
+ {
105
+ "match": "[←⎕⋄\\?₀₁₂₃₄₅₆₇₈₉₋]",
106
+ "name": "keyword.control.bpl"
107
+ }
108
+ ]
109
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "hpl",
3
+ "displayName": "BPL (Hanzi)",
4
+ "scopeName": "source.hpl",
5
+ "fileTypes": [
6
+ "hpl"
7
+ ],
8
+ "patterns": [
9
+ {
10
+ "begin": "[注]",
11
+ "beginCaptures": {
12
+ "0": {
13
+ "name": "comment.line.bpl"
14
+ }
15
+ },
16
+ "end": "$",
17
+ "contentName": "comment.line.bpl",
18
+ "patterns": [],
19
+ "applyEndPatternLast": true
20
+ },
21
+ {
22
+ "match": "(?:_\\d+|_\\S|_|[^\\s\\p{Cc}0-9←是⎕出入•系⍺甲⍵乙⍶丙⍹丁∇递遞⍢循⍝注⋄句\\?若¯负負∞永⍬空\\+加\\-减減×乘号號÷除⌈上⌊下\\|绝余絕餘\\*幂冪⍟对對○圆圓π周√根!阶拣階揀∧极且極∨析或⊼方否⊽双莫雙\\~非无無=等≠别初別<小≤限退>大≥达进達進⍳位↦至:键卸鍵⍴形≢数异數異≡同深,连連⍪接矩⊂包⊃选合選⊆巢段∊属展屬∪并独併獨∩交重⍋升⍒降↑取↓去拆⌽转轉⊖纵縱⍉翻⊤编編⊥译譯⍎行⍕文⌷索⌹解逆\\#复複↕窗⍭素⨸因⌻零值⍸处间處間⍷寻群尋⊢右⊣左¿掷抽擲¨遍ᵇ按⍨己换換↣先⍤秩∘承⍠轴軸⍥经經↢后後\\.内內⊗表⌸组組⍣次止⇄优優⊘兼@于於∂导梯導⍚择擇⌺邻鄰/总總⌿汇匯\\\\累⍀续續⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ₀₁₂₃₄₅₆₇₈₉₋\\(\\)\\[\\]\\{\\}'\";\\$_ₑⱼᵣ])+",
23
+ "name": "variable.other.bpl"
24
+ },
25
+ {
26
+ "match": "[•系][A-Za-z_∆⍙][A-Za-z0-9_∆⍙]*",
27
+ "name": "support.function.system.bpl"
28
+ },
29
+ {
30
+ "match": "[¯负負]?[∞永]|[¯负負]?(\\d+([.内內]\\d+)?|[.内內]\\d+)([eEₑ][¯负負]?\\d+)?([jJⱼ][¯负負]?(\\d+([.内內]\\d+)?|[.内內]\\d+)([eEₑ][¯负負]?\\d+)?|ₓ|[rᵣ][¯负負]?\\d+)?|[ₑⱼᵣ]",
31
+ "name": "constant.numeric.bpl"
32
+ },
33
+ {
34
+ "match": "[⍬空]ₓ?",
35
+ "name": "constant.numeric.bpl"
36
+ },
37
+ {
38
+ "match": "[加减減乘号號除上下绝余絕餘幂冪对對圆圓周根阶拣階揀极且極析或方否双莫雙非无無等别初別小限退大达进達進位至键卸鍵形数异數異同深连連接矩包选合選巢段属展屬并独併獨交重升降取去拆转轉纵縱翻编編译譯行文索解逆复複窗素因零值处间處間寻群尋右左掷抽擲]",
39
+ "name": "support.function.bpl"
40
+ },
41
+ {
42
+ "match": "[遍按己换換表组組优優导梯導总總汇匯累续續]",
43
+ "name": "keyword.operator.monadic.bpl"
44
+ },
45
+ {
46
+ "match": "[先秩承轴軸经經后後内內次止兼于於择擇邻鄰]",
47
+ "name": "keyword.operator.dyadic.bpl"
48
+ },
49
+ {
50
+ "match": "[甲乙丙丁递遞循]",
51
+ "name": "variable.parameter.bpl"
52
+ },
53
+ {
54
+ "match": "[是出入句若]",
55
+ "name": "keyword.control.bpl"
56
+ },
57
+ {
58
+ "include": "source.bpl"
59
+ }
60
+ ]
61
+ }
@@ -8,7 +8,7 @@ Syntax highlighting and glyph-entry templates for IntelliJ IDEA, PyCharm, WebSto
8
8
  2. Under **Settings > Editor > TextMate Bundles**, click **+** and select this folder's `BPL.tmbundle` directory.
9
9
  3. Open a `.bpl` file.
10
10
 
11
- The bundle contains the same generated TextMate grammar used by BPL's playground. See JetBrains' [TextMate instructions](https://www.jetbrains.com/help/idea/textmate.html).
11
+ The bundle contains the same generated TextMate grammars used by BPL's playground. Select **BPL (Hanzi)** for Hanzi glyph spellings (`.hpl` files). **BPL** treats Hanzi as names. See JetBrains' [TextMate instructions](https://www.jetbrains.com/help/idea/textmate.html).
12
12
 
13
13
  ## Glyph entry
14
14
 
@@ -0,0 +1,33 @@
1
+ if exists('b:current_syntax')
2
+ finish
3
+ endif
4
+
5
+ syntax match bplName /\v%(_\d+|_\S|_|[^\s\x00-\x1f\x7f-\x9f0-9←⎕•⍺⍵⍶⍹∇⍢⍝⋄\?¯∞⍬\+\-×÷⌈⌊\|\*⍟○π√!∧∨⊼⊽\~=≠<≤>≥⍳↦:⍴≢≡,⍪⊂⊃⊆∊∪∩⍋⍒↑↓⌽⊖⍉⊤⊥⍎⍕⌷⌹\#↕⍭⨸⌻⍸⍷⊢⊣¿¨ᵇ⍨↣⍤∘⍠⍥↢\.⊗⌸⍣⇄⊘@∂⍚⌺\/⌿\\⍀⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ₀₁₂₃₄₅₆₇₈₉₋\(\)\[\]\{\}'";\$_ₑⱼᵣ])+/
6
+ syntax match bplSystem /\v[•][A-Za-z_∆⍙][A-Za-z0-9_∆⍙]*/
7
+ syntax match bplString /\v\$[ad]/
8
+ syntax match bplFunction /[+×÷⌈⌊|*⍟○π√!∧∨⊼⊽~=≠<≤>≥⍳↦:⍴≢≡,⍪⊂⊃⊆∊∪∩⍋⍒↑↓⌽⊖⍉⊤⊥⍎⍕⌷⌹#↕⍭⨸⌻⍸⍷⊢⊣¿-]/
9
+ syntax match bplMonadicOperator #[¨ᵇ⍨⊗⌸⇄∂/⌿\\⍀⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ]#
10
+ syntax match bplDyadicOperator /[↣⍤∘⍠⍥↢.⍣⊘@⍚⌺]/
11
+ syntax match bplArgument /[⍺⍵⍶⍹∇⍢]/
12
+ syntax match bplKeyword /[←⎕⋄?₀₁₂₃₄₅₆₇₈₉₋]/
13
+ syntax match bplNumber /\v[¯]?[∞]|[¯]?(\d+([.]\d+)?|[.]\d+)([eEₑ][¯]?\d+)?([jJⱼ][¯]?(\d+([.]\d+)?|[.]\d+)([eEₑ][¯]?\d+)?|ₓ|[rᵣ][¯]?\d+)?|[ₑⱼᵣ]|[⍬]ₓ?/
14
+ syntax match bplNumber /\v([\])])@<=ₓ/
15
+ syntax match bplNumber /\v\$[tfn]/
16
+ syntax match bplCharacter /'.\?'/
17
+ syntax region bplString oneline start=/"/ skip=/""/ end=/"/
18
+ syntax match bplComment /\v⍝.*$/
19
+ syntax match bplComment /\%^#!.*/
20
+
21
+ highlight default link bplName Identifier
22
+ highlight default link bplSystem PreProc
23
+ highlight default link bplNumber Number
24
+ highlight default link bplFunction Function
25
+ highlight default link bplMonadicOperator Operator
26
+ highlight default link bplDyadicOperator Type
27
+ highlight default link bplArgument Special
28
+ highlight default link bplKeyword Statement
29
+ highlight default link bplCharacter Character
30
+ highlight default link bplString String
31
+ highlight default link bplComment Comment
32
+
33
+ let b:current_syntax = 'bpl'
@@ -5,7 +5,7 @@ format:
5
5
  html:
6
6
  theme: cosmo
7
7
  css: [fonts.css, styles.css]
8
- syntax-definitions: [bpl.xml, dyalog.xml, bqn.xml]
8
+ syntax-definitions: [bpl.xml, hpl.xml, dyalog.xml, bqn.xml]
9
9
  toc: true
10
10
  commonmark: default
11
11