basedpl 0.1.61__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.
- {basedpl-0.1.61 → basedpl-0.1.63}/.github/workflows/test.yml +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/Cargo.lock +12 -20
- {basedpl-0.1.61 → basedpl-0.1.63}/Cargo.toml +8 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/DEV.md +36 -26
- {basedpl-0.1.61 → basedpl-0.1.63}/PKG-INFO +2 -1
- basedpl-0.1.63/editors/jetbrains/BPL.tmbundle/Syntaxes/bpl.tmLanguage.json +109 -0
- basedpl-0.1.63/editors/jetbrains/BPL.tmbundle/Syntaxes/hpl.tmLanguage.json +61 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/jetbrains/README.md +1 -1
- basedpl-0.1.63/editors/vim/syntax/bpl.vim +33 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/array.bpl +12 -12
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/dyalog.bpl +27 -27
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/graph.bpl +12 -12
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/numeric.bpl +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/string.bpl +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/tree.bpl +8 -8
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/_quarto.yml +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/arrays.ipynb +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/assignment.ipynb +32 -3
- basedpl-0.1.63/nbs/bpl.xml +52 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/comparison.qmd +11 -11
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/data.ipynb +12 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/distributions.ipynb +6 -6
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/evaluation.qmd +8 -5
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/alpha-underbar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/alpha.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/at.qmd +12 -10
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/backslash-bar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/backslash.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/bullet.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-backslash.qmd +16 -16
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-bar.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-diaeresis.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-divide.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-slash.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-star.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-stile.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle-times.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/circle.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/colon.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/comma-bar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/comma.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/del-diaeresis.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/del-stile.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/del.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/delta-stile.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/diaeresis.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/diamond-underbar.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/diamond.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/domino.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/dot.qmd +11 -11
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/down-arrow.qmd +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/down-shoe.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/down-tack.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/downstile.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/epsilon-underbar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/epsilon.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/equal-underbar-slash.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/equal-underbar.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/equals.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/exclamation.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/greater-than-or-equal.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/greater-than.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/hash.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/hydrant.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/infinity.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/inverted-question.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/iota-underbar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/iota.qmd +5 -5
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/jot-diaeresis.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/jot.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/lamp.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/left-arrow.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/left-shoe-underbar.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/left-shoe.qmd +5 -5
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/left-tack.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/left-tail-arrow.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/less-than-or-equal.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/less-than.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/minus.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/not-equals.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/obelus.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/omega-underbar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/omega.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/overbar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/partial.qmd +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/pi.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/plus.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/quad-colon.qmd +20 -20
- basedpl-0.1.63/nbs/glyphs/quad-diamond.qmd +37 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/quad-equal.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/quad-jot.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/quad.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/question.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/radical.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/rho.qmd +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/right-arrow-from-bar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/right-left-arrows.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/right-shoe.qmd +5 -5
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/right-tack.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/right-tail-arrow.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/slash-bar.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/slash.qmd +9 -9
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/squad.qmd +28 -27
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/star-diaeresis.qmd +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/star.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/stile-tilde.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/stile.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/superscript-b.qmd +1 -1
- basedpl-0.1.63/nbs/glyphs/thorn.qmd +33 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/tilde-diaeresis.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/tilde.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/times.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/up-arrow.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/up-down-arrow.qmd +17 -9
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/up-shoe.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/up-tack.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/upstile.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/vee-bar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/vee.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/wedge-bar.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/wedge.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/zilde.qmd +1 -1
- basedpl-0.1.63/nbs/glyphs-study.qmd +13 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/hanzi-notation-zh.ipynb +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/hanzi-notation.ipynb +1 -1
- basedpl-0.1.63/nbs/hpl.xml +40 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/indexing.ipynb +13 -13
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/introspection.ipynb +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/keyed.ipynb +26 -26
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/llms.txt +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/numbers.qmd +19 -8
- basedpl-0.1.63/nbs/playground/hpl.tmLanguage.json +61 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/principles.ipynb +8 -8
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/python.ipynb +241 -625
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/repl.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/scripts.ipynb +11 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/sidebar.yml +2 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/strings.ipynb +1 -1
- basedpl-0.1.63/nbs/study/01_basics.ipynb +4617 -0
- basedpl-0.1.63/nbs/study/02_functions.ipynb +3383 -0
- basedpl-0.1.63/nbs/study/03_operators.ipynb +4540 -0
- basedpl-0.1.63/nbs/study/04_nested-arrays.ipynb +3812 -0
- basedpl-0.1.63/nbs/study/05_searching-indexing.ipynb +2961 -0
- basedpl-0.1.63/nbs/study/06_rearranging-arrays.ipynb +2025 -0
- basedpl-0.1.63/nbs/study/07_numerical-tools.ipynb +554 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/style.qmd +4 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/styles.css +17 -16
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/syntax.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/edge.qmd +4 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/explain.qmd +19 -10
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/index.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/memory.qmd +2 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/prefs.qmd +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/storage.qmd +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/py/Cargo.toml +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/py/src/lib.rs +170 -126
- {basedpl-0.1.61 → basedpl-0.1.63}/pyproject.toml +3 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/__init__.py +31 -75
- basedpl-0.1.63/python/basedpl/bpl.tmLanguage.json +109 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/bpltests.py +82 -41
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/editors.py +72 -24
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/functions.py +4 -5
- basedpl-0.1.63/python/basedpl/hpl.tmLanguage.json +61 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/notebook_runner.py +4 -2
- {basedpl-0.1.61 → basedpl-0.1.63}/src/array/storage.rs +90 -67
- {basedpl-0.1.61 → basedpl-0.1.63}/src/array/text.rs +28 -22
- {basedpl-0.1.61 → basedpl-0.1.63}/src/array.rs +45 -35
- basedpl-0.1.63/src/batch.rs +472 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/data.rs +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/src/derivative.rs +192 -147
- {basedpl-0.1.61 → basedpl-0.1.63}/src/display.rs +87 -47
- {basedpl-0.1.61 → basedpl-0.1.63}/src/distribution.rs +8 -8
- {basedpl-0.1.61 → basedpl-0.1.63}/src/element.rs +4 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/error.rs +2 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/assign.rs +58 -45
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/binder.rs +47 -70
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/idioms.rs +12 -12
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/operators.rs +388 -274
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/session.rs +190 -174
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/tree.rs +33 -14
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval.rs +101 -165
- {basedpl-0.1.61 → basedpl-0.1.63}/src/execution.rs +23 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/src/explain.rs +105 -24
- {basedpl-0.1.61 → basedpl-0.1.63}/src/fusion/blocks.rs +11 -16
- {basedpl-0.1.61 → basedpl-0.1.63}/src/fusion.rs +72 -127
- {basedpl-0.1.61 → basedpl-0.1.63}/src/js.rs +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/src/json.rs +4 -4
- {basedpl-0.1.61 → basedpl-0.1.63}/src/keyed.rs +3 -9
- {basedpl-0.1.61 → basedpl-0.1.63}/src/lib.rs +1 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/linear.rs +118 -101
- {basedpl-0.1.61 → basedpl-0.1.63}/src/number.rs +83 -55
- {basedpl-0.1.61 → basedpl-0.1.63}/src/optimize.rs +7 -7
- {basedpl-0.1.61 → basedpl-0.1.63}/src/pervasive.rs +211 -216
- {basedpl-0.1.61 → basedpl-0.1.63}/src/primitive/indexing.rs +207 -152
- {basedpl-0.1.61 → basedpl-0.1.63}/src/primitive/numeric.rs +37 -24
- {basedpl-0.1.61 → basedpl-0.1.63}/src/primitive/search.rs +18 -15
- {basedpl-0.1.61 → basedpl-0.1.63}/src/primitive/structural.rs +42 -23
- {basedpl-0.1.61 → basedpl-0.1.63}/src/primitive.rs +192 -75
- {basedpl-0.1.61 → basedpl-0.1.63}/src/protocol.rs +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/src/reference.rs +155 -100
- {basedpl-0.1.61 → basedpl-0.1.63}/src/search.rs +6 -6
- basedpl-0.1.63/src/selection.rs +361 -0
- basedpl-0.1.63/src/settings.rs +71 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/symbols.rs +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/src/syntax.rs +15 -16
- {basedpl-0.1.61 → basedpl-0.1.63}/src/system.rs +17 -16
- {basedpl-0.1.61 → basedpl-0.1.63}/src/timing.rs +116 -33
- {basedpl-0.1.61 → basedpl-0.1.63}/src/transform.rs +157 -84
- basedpl-0.1.63/tests/common/mod.rs +56 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/core.rs +3 -241
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/explain.rs +26 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/highlighting.mjs +17 -11
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/README.md +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/aplcart.bpl +519 -517
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/april.bpl +775 -791
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/bqn.bpl +9 -9
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/core.bpl +694 -440
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/distributions.bpl +11 -11
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/dyalog.bpl +21 -21
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/graphics.bpl +5 -5
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/lib.bpl +3 -3
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/ngn.bpl +112 -112
- basedpl-0.1.63/tests/reference/static-int32.bpl +11 -0
- basedpl-0.1.63/tests/reference/static.bpl +23 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference.rs +15 -15
- basedpl-0.1.63/tests/settings.rs +205 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/speed.rs +1 -1
- basedpl-0.1.63/tests/speed.txt +812 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_api.py +8 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_basic.py +1 -1
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_bpltests.py +11 -13
- basedpl-0.1.61/editors/jetbrains/BPL.tmbundle/Syntaxes/bpl.tmLanguage.json +0 -108
- basedpl-0.1.61/editors/vim/syntax/bpl.vim +0 -33
- basedpl-0.1.61/nbs/bpl.xml +0 -52
- basedpl-0.1.61/nbs/glyphs/quad-diamond.qmd +0 -39
- basedpl-0.1.61/nbs/glyphs/thorn.qmd +0 -24
- basedpl-0.1.61/python/basedpl/bpl.tmLanguage.json +0 -108
- basedpl-0.1.61/src/batch.rs +0 -433
- basedpl-0.1.61/src/selection.rs +0 -130
- basedpl-0.1.61/tests/speed.txt +0 -457
- {basedpl-0.1.61 → basedpl-0.1.63}/.cargo/config.toml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/.gitattributes +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/.github/workflows/ci.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/.github/workflows/docs.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/.github/workflows/speed.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/.gitignore +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/CONTRIBUTING.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/LICENSE +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/README.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/_config.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/_layouts/default.html +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/build.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/jetbrains/BPL.tmbundle/info.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/jetbrains/BPL.xml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.icns +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.keylayout +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-de.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-de.txt +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.icns +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.keylayout +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-es.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-es.txt +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.icns +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.keylayout +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-fr.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-fr.txt +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.icns +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.keylayout +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-uk.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-uk.txt +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.icns +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.keylayout +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-us.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/macos/BasedPL-us.txt +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/vim/ftdetect/bpl.vim +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/README.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/build.ps1 +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/install.ps1 +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/keyboard.c +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/keyboard.def +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/keyboard.rc +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/editors/windows/layout.h +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/index_files/figure-commonmark/cell-17-output-1.svg +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/index_files/figure-commonmark/cell-18-output-1.svg +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/index_files/figure-html/cell-17-output-1.svg +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/index_files/figure-html/cell-18-output-1.svg +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/LICENSE-april +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/README.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/power.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/lib/regex.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/.gitignore +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/bqn.xml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/bracket-types.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/cli.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/dfns.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/driver.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/dyalog.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/dyalog.xml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/fonts/LICENSE-SAX2 +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/fonts/README.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/fonts/SAX2B.ttf +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/fonts/SAX2B.woff2 +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/fonts.css +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/attractor.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/boids.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/dragon.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/flow.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/mandelbrot.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/mandelbrot32.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/orbits.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/phyllotaxis.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/prefs.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery/reaction.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/gallery.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/getting-started.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/_metadata.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/braces.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/brackets.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/error-guard.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/parentheses.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs/quote.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/glyphs.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/index.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/keyboard.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/magics.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/modules.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/nbdev.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/notebooks.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/overview.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/papers/aplwiki-arrays.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/papers/brickman-depth-1-scalars.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/papers/mercer-based-system.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/playground/bpl.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/playground/gallery.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/playground/monaco-worker.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/playground/page.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/playground/worker.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/playground.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/plot.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/processes.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/puppy.jpg +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/regex.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/_metadata.yml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/c.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/canvas.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/constants.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/copy.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/csv.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/date.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/decompose.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/deflate.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/delay.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/detach.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/distribution.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/element.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/ex.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/fetch.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/float.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/hash.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/host.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/image.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/js.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/json.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/literal.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/load.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/metadata.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/mime.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/mkdir.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/nc.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/nget.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/nl.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/normalize.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/nput.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/path.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/plot.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/r.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/rand.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/readdir.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/remove.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/rename.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/signal.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/src.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/svg.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/time.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/ucs.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/uuid.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/vfi.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system/xml.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/system-functions.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/terms.qmd +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/web.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/nbs/xml.ipynb +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/package-lock.json +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/package.json +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/README.md +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/aplcart.jsonl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/april.jsonl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/bqn.jsonl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/core.jsonl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/dyalog.jsonl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/provenance/ngn.jsonl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/py/build.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/_modidx.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/dyalog.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/font.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/fonts.css +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/input.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/ipython.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/keyboards.json +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/keyboards.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/layout.json +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/lb.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/notebooks.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/printing.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/reference.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/syntax.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/windows_keyboard.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/python/basedpl/worker.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/rustfmt.toml +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/scripts/install-macos.sh +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/scripts/prep.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/agreement.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/canvas.js +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/canvas.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/csv.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/date.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/eval/dissect.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/files.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/host.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/host_web.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/image/codecs.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/image/imageio.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/image.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/inspection.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/number_theory.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/plot.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/polynomial.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/regex.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/src/xml.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/conftest.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/derivatives.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/input.mjs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/LICENSE-aplcart +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/LICENSE-april +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/LICENSE-bqn +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/LICENSE-bqncrate +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/LICENSE-dyalog +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/LICENSE-ngn +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/regex.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/support/april.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/support/avl.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/support/redblack.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/support/sbst.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/reference/support/splay.bpl +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/scaling.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_glyphs.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_graphics.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_ipython.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_kernel.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_keylayout.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_notebooks.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_reference.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_repl.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_windows_keyboard.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/test_worker.py +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/units.rs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/wasm-pkg.mjs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/wasm-speed.mjs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/wasm.mjs +0 -0
- {basedpl-0.1.61 → basedpl-0.1.63}/tests/windows_keyboard.c +0 -0
- {basedpl-0.1.61 → 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.
|
|
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.
|
|
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.
|
|
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.
|
|
168
|
+
version = "0.1.63"
|
|
172
169
|
dependencies = [
|
|
173
170
|
"basedpl",
|
|
174
171
|
"js-sys",
|
|
@@ -345,9 +342,9 @@ dependencies = [
|
|
|
345
342
|
|
|
346
343
|
[[package]]
|
|
347
344
|
name = "crc32fast"
|
|
348
|
-
version = "1.5.
|
|
345
|
+
version = "1.5.3"
|
|
349
346
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
350
|
-
checksum = "
|
|
347
|
+
checksum = "0ba106e844045ddc02c20768ac4b0b7cb45f2cc2ecbd833ac9f5dacb183c2055"
|
|
351
348
|
dependencies = [
|
|
352
349
|
"cfg-if",
|
|
353
350
|
]
|
|
@@ -1416,10 +1413,11 @@ dependencies = [
|
|
|
1416
1413
|
|
|
1417
1414
|
[[package]]
|
|
1418
1415
|
name = "rustymath"
|
|
1419
|
-
version = "0.1.
|
|
1416
|
+
version = "0.1.40"
|
|
1420
1417
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1421
|
-
checksum = "
|
|
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.
|
|
1436
|
+
version = "0.1.40"
|
|
1439
1437
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1440
|
-
checksum = "
|
|
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.
|
|
2088
|
+
version = "0.1.63"
|
|
2097
2089
|
dependencies = [
|
|
2098
2090
|
"anyhow",
|
|
2099
2091
|
"rustymath",
|
|
@@ -5,11 +5,17 @@ members = ["py"]
|
|
|
5
5
|
join_comments = true
|
|
6
6
|
|
|
7
7
|
[workspace.package]
|
|
8
|
-
version = "0.1.
|
|
8
|
+
version = "0.1.63"
|
|
9
9
|
edition = "2024"
|
|
10
10
|
rust-version = "1.98"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
|
|
13
|
+
[workspace.dependencies]
|
|
14
|
+
rustymath = { version = ">=0.1.40, <1", default-features = false }
|
|
15
|
+
rustymath-buffer = ">=0.1.40, <1"
|
|
16
|
+
pyo3 = ">=0.29.2, <1"
|
|
17
|
+
pyo3-build-config = ">=0.29.2, <1"
|
|
18
|
+
|
|
13
19
|
[package]
|
|
14
20
|
name = "basedpl"
|
|
15
21
|
version.workspace = true
|
|
@@ -54,20 +60,18 @@ tempfile = "3"
|
|
|
54
60
|
serde = ">=1.0.229, <2"
|
|
55
61
|
serde_json = { version = "1", features = ["arbitrary_precision", "preserve_order"] }
|
|
56
62
|
unicode-width = { version = ">=0.2.2, <1", default-features = false }
|
|
57
|
-
unicode-script = "0.5"
|
|
58
63
|
num-rational = ">=0.4.2, <1"
|
|
59
64
|
num-complex = { version = ">=0.4.6, <1", features = ["bytemuck"] }
|
|
60
65
|
num-bigint = ">=0.4.6, <0.5"
|
|
61
66
|
num-traits = ">=0.2.19, <1"
|
|
62
67
|
half = { version = ">=2.7.1, <3", features = ["num-traits", "bytemuck"] }
|
|
63
|
-
rustymath
|
|
68
|
+
rustymath.workspace = true
|
|
64
69
|
strength_reduce = ">=0.2.4, <1"
|
|
65
70
|
rand = { version = ">=0.10.2, <1", features = ["chacha"] }
|
|
66
71
|
# AnswerDotAI's fork measures text with a canvas, which works in a Web Worker: plotters-rs/plotters#746.
|
|
67
72
|
plotters = { git = "https://github.com/AnswerDotAI/plotters.git", branch = "master", default-features = false, features = ["svg_backend", "colormaps", "full_palette"] }
|
|
68
73
|
base64 = ">=0.22.1, <1"
|
|
69
74
|
stacker = ">=0.1.25, <1"
|
|
70
|
-
foldhash = ">=0.2.0, <1"
|
|
71
75
|
bytemuck = { version = ">=1.25.2, <2", features = ["extern_crate_alloc"] }
|
|
72
76
|
json5 = ">=1.3.1, <2"
|
|
73
77
|
roxmltree = { version = ">=0.21.1, <1", default-features = false, features = ["std"] }
|
|
@@ -10,13 +10,15 @@ A form with a reasonable meaning gives a result, not an error. A result that wou
|
|
|
10
10
|
|
|
11
11
|
LLMS: Read `nbs/llms.txt` in full before doing any work. BPL differs substantially from Dyalog APL in grouping, names, numbers and operators. Use BPL syntax, not APL idioms assumed to carry over. The links in `nbs/llms.txt` are relative to the published site. In this repository, read each linked page's source under `nbs/`, as in `nbs/glyphs/at.qmd` for `glyphs/at.html.md` and `nbs/indexing.ipynb` for `indexing.html.md`. The published site lacks unreleased changes.
|
|
12
12
|
|
|
13
|
+
Rustymath and basedpl have no outside users yet, so treat neither as published. Changing rustymath to give both projects shared machinery is encouraged. Separate machinery in the two for the same task is an error, unless Jeremy has asked for them to differ there.
|
|
14
|
+
|
|
13
15
|
```bash
|
|
14
16
|
cargo develop
|
|
15
17
|
cargo test
|
|
16
|
-
pytest
|
|
18
|
+
pytest -q
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
Use `cargo develop` to rebuild and install the native extension and `bpl` after Rust changes. It uses the `test` profile shared with `cargo test`. Cargo tests compile missing code but don't install it. Run plain `cargo test` while you work; use one test binary for a focused check. Run `pytest` at the end of a piece of work. Before you report a `pytest` failure in code you didn't touch, run `cargo develop` and rerun it. Give builds three minutes and test runs one minute; Cargo serializes builds in the same target directory.
|
|
21
|
+
Use `cargo develop` to rebuild and install the native extension and `bpl` after Rust changes. It uses the `test` profile shared with `cargo test`. Cargo tests compile missing code but don't install it. Run plain `cargo test` while you work; use one test binary for a focused check. Run `pytest -q` at the end of a piece of work. Before you report a `pytest` failure in code you didn't touch, run `cargo develop` and rerun it. Give builds three minutes and test runs one minute; Cargo serializes builds in the same target directory.
|
|
20
22
|
|
|
21
23
|
Build nothing else without discussion: no scratch crates, alternate target directories, `--release`, `-p` or other-target builds. The documented build diagnostics, browser work and x86-64 inspection below are exceptions. Don't use `maturin develop`; its configuration does not reuse the normal local build.
|
|
22
24
|
|
|
@@ -26,13 +28,19 @@ An already-running Python process retains its loaded extension. In a kernel, use
|
|
|
26
28
|
|
|
27
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.
|
|
28
30
|
|
|
29
|
-
|
|
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.
|
|
34
|
+
|
|
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.
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
An initial budget is twice what a first-principles analysis says the case should cost, as each budget file's header says. A later budget comes from a fuller understanding of the case than that analysis gives, such as a platform difference or a cost the analysis missed, and the case's comment records it. A case over its budget needs study, which finds either a speed bug to fix or something the analysis missed. Avoid raising a budget to match a run without understanding why the case costs what it does. Each case line in a budget file holds a native budget for macOS on Apple silicon, then one for Linux on CI's x86 runner, then, in basedpl's file, a wasm budget. One expected cost serves every platform at first, until a specific difference on one platform is found. macOS running matrix products and decompositions on Accelerate, where CI runs rustymath's own kernels, is such a difference. A comment above each case, or above its group, gives the expected cost with its reason, and any platform's own cost with the reason for it. `set_budgets(expected)` writes the budgets for the cases that `expected` names, a dict from each case's code to its expected cost. `builds=` limits the change to one platform's column, for a cost that differs there. A case can appear in more than one section, such as `[copies]` and `[widths]`. `sections=` limits the change to the sections it names. `path=` selects one of rustymath's budget files, `tests/speed.txt` or `tests/speed_python.txt`.
|
|
38
|
+
|
|
39
|
+
`tests/explain.rs`'s `speed_cases_take_their_routes` runs each speed case once more, after a warm-up run, as `•explain` runs its text (`timing::routes`). It fails on any slow-path event that the case's lines don't name: a pending array that a fused group computed on its own (`stored`), a call that computed pending items (`forced`), a batched map's fallback (`fallbacks`), a write that left an array mixed (`mixed`), or a route that handled items one at a time (`itemwise`). A line above a case names one event, as `•explain`'s record names it: the function for `forced`, the reason for `stored` and `fallbacks`, the code for `mixed` and the route for `itemwise`. `# allows RECORD "EVENT": principle` names an event that a principle allows, such as a matrix product reading its arguments whole. `# gap RECORD "EVENT": what should happen` names an event that a faster route should remove, and the test prints these gaps, which `cargo test -- --nocapture` shows. Any other event is a route to study, as a case over its budget is: add an `allows` line only for a principle, and a `gap` line once the study finds what should happen. The test also fails on a line whose event no longer appears, so a fixed gap's line goes.
|
|
32
40
|
|
|
33
41
|
The speed tests and the scaling test time each failing case again after the rest, after each pause in `rustymath::timing::RETRY_PAUSES`, and fail only for a case that fails every time. Each retry prints the case's earlier and new costs, even in a passing run. `logged_costs` keeps a retried case's lowest cost. Study a case that needs a retry in most runs, as you would a slowdown.
|
|
34
42
|
|
|
35
|
-
For a change meant to make something faster, or a change to code that every call goes through, time the cases it affects before and after the change. Before your first `cargo develop`, copy the installed `bpl` in the kernel with `shutil.copy(basedpl.worker.INSTALLED_BPL, '/tmp/<prefix>_bpl')`. Time that copy with `bpl='/tmp/<prefix>_bpl'`, and your build with the default. Another agent's `cargo develop` can replace the installed `bpl` at any time. The copy keeps your baseline fixed while agents build in parallel. Because costs in copies correct for the machine's overall speed, the two timings compare directly at the 20% level that review looks for. On this Mac, a fused case over a large input can cost up to about 15% more in one process than in another, depending on whether `malloc` starts the input on a 32 KB boundary, where every one of a graph's blocks then ends. Time both builds the same way, each alone in a fresh process or at the same place in one run, and alternate them before you read a lone difference of that size as a regression.
|
|
43
|
+
For a change meant to make something faster, or a change to code that every call goes through, time the cases it affects before and after the change. Before your first `cargo develop`, copy the installed `bpl` in the kernel with `shutil.copy(basedpl.worker.INSTALLED_BPL, '/tmp/<prefix>_bpl')`. Time that copy with `bpl='/tmp/<prefix>_bpl'`, and your build with the default. Another agent's `cargo develop` can replace the installed `bpl` at any time. The copy keeps your baseline fixed while agents build in parallel. Because costs in copies correct for the machine's overall speed, the two timings compare directly at the 20% level that review looks for. On this Mac, a fused case over a large input can cost up to about 15% more in one process than in another, depending on whether `malloc` starts the input on a 32 KB boundary, where every one of a graph's blocks then ends. Time both builds the same way, each alone in a fresh process or at the same place in one run, and alternate them before you read a lone difference of that size as a regression. The speed test fails a case only past its budget. It misses any smaller slowdown. Other changes need only the speed test. Don't restore old code in the shared tree to get a baseline. On macOS, native timings of matrix products and decompositions mostly measure Accelerate. Rustymath's DEV.md says how to time rustymath's own kernels.
|
|
36
44
|
|
|
37
45
|
Cooperating tools share the machine's timing lock, `/tmp/aai-ws-timing.lock`. Timings take it exclusively. `cargo develop`, `cargo wait`, `cargo wasm`, the reference test, pytest and `wasm_test` without `speed` take it shared. Rust code takes it through `rustymath::timing`. Python code takes it with `fastws.cargo.timing_lock`. Node can't lock a file. `wasm_test` and `speed_costs(wasm=DIR)` hold the lock in Python while Node runs. Other Rust tests and bare Cargo commands do not all take it. After five minutes a timing fails. A build or test run then goes ahead without the lock. After 30 seconds, an exclusive wait prints the processes with the lock file open. The list can include processes that are only waiting for the lock. Never take the lock yourself in the shared kernel process. Never coordinate timings by hand. A hold that outlasts its call blocks the timings that later calls launch. Each such call stalls every other agent's kernel calls while it waits. Native timings run on one thread and request user-interactive macOS QoS, which favours the performance cores. QoS is not CPU affinity.
|
|
38
46
|
|
|
@@ -95,7 +103,7 @@ Use `cargo build --lib --bins --profile test --timings` to inspect the normal bu
|
|
|
95
103
|
| `number.rs`, `element.rs`, `pervasive.rs`, `fusion.rs`, `explain.rs` | Numeric domains, item operations, compact kernels, pending arrays with the graphs that compute them, and the events that `•explain` records and the live nodes that `•memory` counts. |
|
|
96
104
|
| `derivative.rs`, `linear.rs` | `∂`: duals, tags, seeding, the partials table and the rules for operators, and the record of linear calls that reverse mode transposes. |
|
|
97
105
|
| `transform.rs` | The core that running transformations share: one stack of levels, routing to the newest level among a call's arguments, and the read point for code that isn't a call. |
|
|
98
|
-
| `batch.rs` | Batched maps: the batch carrier, the try in `each_pair` that calls the operand of an Each, a Rank
|
|
106
|
+
| `batch.rs` | Batched maps: the batch carrier, the try in `each_pair` that calls the operand of an Each, a Rank or an outer product once on batches of its cells while the `batch` pref is on, and the batch rules that routing hands calls to. The pref is on by default. `tests/reference.rs` runs every reference case with it off and on. `bpl-tests check_page PAGE --unbatched` checks a page with it off. |
|
|
99
107
|
| `search.rs`, `number_theory.rs`, `polynomial.rs`, `distribution.rs` | Array-level adapters to rustymath. |
|
|
100
108
|
| `system.rs`, `data.rs` | System-function metadata, native functions, options and import rules. |
|
|
101
109
|
| `csv.rs`, `json.rs`, `xml.rs`, `image.rs`, `plot.rs`, `canvas.rs`, `display.rs` | Formats, rich values and rendering. |
|
|
@@ -110,7 +118,7 @@ User-facing language rules belong in `nbs/syntax.qmd`, `evaluation.qmd`, `number
|
|
|
110
118
|
|
|
111
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.
|
|
112
120
|
|
|
113
|
-
`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.
|
|
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.
|
|
114
122
|
|
|
115
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.
|
|
116
124
|
|
|
@@ -122,9 +130,9 @@ Module 0 owns session names. Each `•load` runs in a new module, without the ca
|
|
|
122
130
|
|
|
123
131
|
Dfns run statements in order and return the last statement's value. Final assignments are silent. An absent left argument propagates through the binder's absent-binding rules; default-left assignment runs only when needed. Guard handlers see bindings as they stood at failure; nothing rolls back. Wildcard `∞::` excludes interrupt, timeout and unsupported errors. Explicit named guards can catch them; catching an interrupt clears its flag.
|
|
124
132
|
|
|
125
|
-
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
|
|
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.
|
|
126
134
|
|
|
127
|
-
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.
|
|
128
136
|
|
|
129
137
|
## Values, layouts and assignment
|
|
130
138
|
|
|
@@ -138,11 +146,11 @@ Numeric storage fills with zero and characters with blank. Mixed nonempty arrays
|
|
|
138
146
|
|
|
139
147
|
`Gather` owns copying and widening. `Steps`, from rustymath's `gather`, describes strides, ranges/fills, rotations and offset tables. `Gather::walk` copies compact storage through `rustymath::gather::walk`. Structural operations should use `remap`/gathering rather than reconstructing `Value`s per item. Equal-shape cells copy in blocks. `Items` reads counts, positions and axes from compact storage without boxing every item. Shape, tally, positions and predicates have dedicated integer/Boolean builders.
|
|
140
148
|
|
|
141
|
-
|
|
149
|
+
Under with a function and selective assignment find their targets through labels. Each begins a label level (`transform::Kind::Label`) and runs the selector, or evaluates the target, on the root wrapped as a `selection::Labelled` value. A primitive whose row selects carries the labels through its own code. Planned forms and `⌷` compose a rustymath `Mapping` relative to the root, so a selection reads only the items it selects. Ordering forms select through `Primitive::taken`. Any other call strips the labels and runs on the values. `Labels::read` takes the labels of the selector's result. Labels that are still a mapping with no fill write back through that mapping, as a walk over the root (`Targets::Walk`). `Labels::replacements` turns any other labels into offsets, or into paths where the root has nested items. A strand of labelled items joins into one labelled array (`Carrier::joins_at_once`). An item that the selector makes rather than selects has the `FOREIGN` label. Writing to it is a DOMAIN ERROR. A result without labels at the level sends Under to the selector's inverse. A batched try refuses while a label level runs (`Levels::admits_batch`). Function-Under applies its selector to a left argument as a plain value. Positions-Under passes the left argument whole. Keyed values align to selected keys, and nested paths retain empty-cell structure.
|
|
142
150
|
|
|
143
151
|
Selective assignment removes the binding before writing. `Arc::make_mut` copies only when another holder needs the old array. Repeated targets must read values written by earlier occurrences. `pervasive::scatter` combines each target of `+ - × ÷ ⌈ ⌊` into compact numbers in place, in turn, at the kind that the call computes in, through rustymath's `try_scatter_with`. Other pervasive modifiers group repeated targets into rounds of distinct positions. A target at a fill reads the fill, and its write is dropped. Append updates use `Value::append` when layouts permit it; rank/key/name changes fall back to ordinary catenation. Modified destructuring calls modifiers left to right; ordinary destructuring assigns right to left. An assignment's RHS runs once.
|
|
144
152
|
|
|
145
|
-
Each, Rank
|
|
153
|
+
Each, Rank and outer products call their operand through `each_pair` in `eval/operators.rs`. It first tries one batched call (`batch::tried`), then calls the operand once for each cell and assembles the results through shared layout and prototype rules. A 0-cell preserves an atom or encloses an array item. For custom operands, empty Each, Rank and outer product calls substitute prototypes for empty arguments and use prototype mode. Explicit effects remain observable when a call runs. Catchable prototype-call failures produce prototype zero, but interrupt, timeout and unsupported errors propagate. Restore prototype mode on success and error. A stencil runs as Rank over `↕`'s windows, and reads its specification through `↕`'s `WindowSpec` (`primitive/structural.rs`).
|
|
146
154
|
|
|
147
155
|
Rank tries `whole` before `each_pair`. `whole` calls the operand once where neither argument has a frame. It then tries `decomposed`, for `•decompose⍤2` on a stack of matrices, and `whole_cells` for a primitive or a product. `whole_cells` holds Rank's routes for whole arguments, which batched calls share (`batch::whole_call`). In order, they are `primitive::stacked`'s kernels for `+.×`, `⌹` and `-.×` on stacks of matrices, one padded call of a pervasive primitive (`padded_call`), `primitive_cells` for a primitive with one argument or with a left argument that every cell shares, and `paired_cells` for a primitive whose arguments' frames match or whose right argument every cell shares. An argument with no axes besides its cells' is the same in every cell. After `whole_cells`, `whole` tries `pervasive_cells`, for a pervasive primitive under nested Rank, and then, for a monadic operand, `cell_rule`, which also takes folds, atops and a bound left argument. `primitive_cells` runs a primitive on the whole argument along the cells' axes. A form that `extends` runs whole at a cell rank at least its own. Other forms follow the `cells` fact (`CellRule`) in their row of `Primitive::info()`. With it, `⊖ , ↑ ↓ ⌷ #` and rotate-first call their axis forms, `⍉` sends each cell's axes after the frame's, `≢` and `⍴` give constants, and a reshape that keeps a cell's items in order is a view. Any other form with a left argument that every cell shares takes `paired_cells`. `paired_cells` joins each pair of cells for `,` and `⍪`, and calls a form that extends once where both cells are at least its ranks. It first repeats an argument that every cell shares over the frame (`agreement::spread`). A pervasive primitive folds or scans a simple array along the cell's axis (`folded_cells`). `f/∘,` folds all the cell axes at once. An atop applies its inner function's rule, then Rank for its outer function. Each rule applies only where Rank's mix of the cells' results gives what the whole-array call gives. Nested results, and folds by other functions, keep the call for each cell.
|
|
148
156
|
|
|
@@ -156,7 +164,7 @@ Inverse nodes propagate fixed-argument sides through composition. `f⁻¹←g` a
|
|
|
156
164
|
|
|
157
165
|
`number.rs` owns scalar kinds, promotion and exactness, and the suffix table that spells numbers (`e`/`ₑ`, `j`/`ⱼ`, `r`/`ᵣ`, `ₓ` and the width marks), which the lexer, `Number::parse` and display read. Integers and BigRational share an exact domain. Overflowing scalar integer arithmetic widens to exact rationals; integral rational results narrow back when possible. Booleans are a distinct kind. Arithmetic reads them as 0/1; logical operations preserve them. Match/search/grade compare their numeric value, while reference checks also distinguish representation and exactness.
|
|
158
166
|
|
|
159
|
-
Joining compact arrays widens Boolean -> integer -> float -> complex, and float widths join at the wider width. Item-by-item construction preserves exact/approximate kinds and stays mixed when needed; only approximate real/complex items widen together. A rearrangement or combination of mixed storage finishes in `Gather::finish`, which holds the items compact where one dtype holds them under the items rule, as a literal of the same items would be. Its scan compares each item's variant with the first item's, so a copy that stays mixed pays little. An in-place write into mixed storage keeps it mixed, because a scan on every write would make a loop of writes quadratic. Fresh computations choose storage from their result path. Results that an operation computes one cell at a time, as Each, Rank, Key,
|
|
167
|
+
Joining compact arrays widens Boolean -> integer -> float -> complex, and float widths join at the wider width. Item-by-item construction preserves exact/approximate kinds and stays mixed when needed; only approximate real/complex items widen together. A write into an existing array follows the items rule (`Widening::Items`), as a literal of the same items would: exact and approximate numbers stay apart, and so do Booleans and other numbers. A rearrangement or combination of mixed storage finishes in `Gather::finish`, which holds the items compact where one dtype holds them under the items rule, as a literal of the same items would be. Its scan compares each item's variant with the first item's, so a copy that stays mixed pays little. An in-place write into mixed storage keeps it mixed, because a scan on every write would make a loop of writes quadratic. Fresh computations choose storage from their result path. Results that an operation computes one cell at a time, as Each, Rank, Key, power histories, and the polynomial and number-theory functions do, assemble as items, through `Value::assemble`. Mix and catenation join arrays. Keep this distinction between whole-array joining and element assembly.
|
|
160
168
|
|
|
161
169
|
Bare numbers, empty literals and NaN use the parsed float width. Top-level `evaluate_code` first validates the whole syntax, runs leading literal-record `•prefs` statements, then parses the remainder at the new width. A syntax error prevents header execution. The default width also applies to imported numbers, random data and float results from exact operands. Time/date/metadata values use f64. Formatting marks non-default widths; serialization marks every float for width-independent readback.
|
|
162
170
|
|
|
@@ -166,7 +174,7 @@ Floats use IEEE NaN, infinity and signed zero. Comparison treats NaN as unequal;
|
|
|
166
174
|
|
|
167
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.
|
|
168
176
|
|
|
169
|
-
|
|
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.
|
|
170
178
|
|
|
171
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.
|
|
172
180
|
|
|
@@ -176,6 +184,8 @@ Only f64 comparisons use the session tolerance, from 0 to `1E-14`. f32/f16 compa
|
|
|
176
184
|
|
|
177
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.
|
|
178
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
|
+
|
|
179
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.
|
|
180
190
|
|
|
181
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.
|
|
@@ -184,7 +194,7 @@ Rustymath owns the mathematical algorithms. Basedpl owns pervasion, storage, num
|
|
|
184
194
|
|
|
185
195
|
A dispatch selects a primitive before its loop. Concrete `Kernels` tables call rustymath objects: `many` for slices and `one`/`checked` for scalar Numbers. `at_widths!` writes f32/f64 tables once. Arithmetic, circle-code conventions and scalar policy remain in the numeric modules rather than a second evaluator.
|
|
186
196
|
|
|
187
|
-
Cheap mixed kernels in `Mixed` convert as they read through `Source`. Other kernels use `Chunked
|
|
197
|
+
Cheap mixed kernels in `Mixed` convert as they read through `Source`. Other kernels use `Chunked`, which reads each argument through rustymath's `Side`, converting a run at a time before calling one homogeneous implementation. Direct conversion loops are worthwhile for cheap arithmetic; sharing expensive kernels avoids a storage-type cross-product of machine code. Compile only operand pairings that can occur. Same-type arguments can reach rustymath in one call; other shapes expand reused chunks or use block mappings to avoid per-item division.
|
|
188
198
|
|
|
189
199
|
Custom elementwise closures use `rustymath::pairs` and its uninitialized append path. Function objects use their own slice forms. Keep per-item bodies inlinable across codegen units; passing a closure by reference can introduce an uninlined `Fn` shim. Pass it by value, or wrap an existing reference in a new closure. Hot loops use slices and fixed chunks rather than iterator helpers that introduce calls in the incremental build. Avoid captured mutable flags that live in memory and block vectorization.
|
|
190
200
|
|
|
@@ -194,15 +204,15 @@ A failed compact kernel leaves placeholder results and triggers a wider/exact/co
|
|
|
194
204
|
|
|
195
205
|
Ordinary pervasive kernels also read pending copies through their maps. `fusion::source` snapshots the source and mapping without taking the pending work, and rustymath composes that mapping with the call's agreement. `pervasive::Input` keeps the snapshot alive while kernels read its storage through existing blocked readers. Folds by rustymath's reductions read a pending copy through `fusion::source` too (`pervasive::mapped_fold`). `reduce::along_mapped` folds a copy that reads a contiguous block of its source with its axes in another order, as `Mapping::block` finds it, in the block's own order. Transposes, reversals and windows that don't overlap read such blocks. Where the totals come out in another order, `pervasive::fold` makes them a copy through the tables that `along_mapped` gives, and the next fold reads that copy as a block again. It reads any other copy block by block. A read of a few items from a pending array goes through `fusion::narrow`, which narrows the pending work to the positions read without consuming it. A chain of copies becomes a read of its source, for any item kind. A call or graph that nothing else holds becomes one over only those positions, when the read takes at most 1 in 128 of its items. Where maps don't compose, as a rotation's doesn't with a take, such a read lists its items' offsets. A pending array that a name holds is computed whole on its first read and keeps its items, so a loop of single reads doesn't compute it again. `fusion::item` serves single items and picks, and `Gather::walk` serves small copies and gathers through `fusion::walk_through`. Checks of a whole input's values, such as bounds and finiteness, read only the items that its logical `ArrayView` selects. Unsupported compositions and dense readers retain the pending array's one cached compact result.
|
|
196
206
|
|
|
197
|
-
`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. 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`.
|
|
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`.
|
|
198
208
|
|
|
199
|
-
`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`
|
|
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.
|
|
200
210
|
|
|
201
|
-
`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.
|
|
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.
|
|
202
212
|
|
|
203
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.
|
|
204
214
|
|
|
205
|
-
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
|
|
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.
|
|
206
216
|
|
|
207
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.
|
|
208
218
|
|
|
@@ -210,7 +220,7 @@ Packed numeric, Boolean and equality-count inner products use `rustymath::linalg
|
|
|
210
220
|
|
|
211
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.
|
|
212
222
|
|
|
213
|
-
`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.
|
|
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.
|
|
214
224
|
|
|
215
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.
|
|
216
226
|
|
|
@@ -222,9 +232,9 @@ Packed numeric, Boolean and equality-count inner products use `rustymath::linalg
|
|
|
222
232
|
|
|
223
233
|
`.fn()` retains a late-bound expression. Calls resolve affected nodes against the calling session while sharing unaffected graph nodes. This preserves primitive fast paths, inverses and reduction identities. The binder still resolves ordinary names during execution. Cyclic resolution is a LIMIT error.
|
|
224
234
|
|
|
225
|
-
Arrays retain native values. `.py` and `.np` make copies; NumPy is optional and lazy. The native `_Array` buffer export lends compact items read-only. An unbuilt structural copy whose read is affine (`Value::affine`) lends its source's items with strides, so windows reach NumPy without being built. Numeric buffers import with one copy through `rustymath_buffer::read_array`. `Value::imported_buffer` preserves supported item widths. The shared reader normalizes signed bytes, wider unsigned integers and foreign byte order. Sibling snapshots carry keys and names. A NumPy uint64 array containing a value above int64's range imports item by item as exact integers. `own()` moves compact items into a writable NumPy array where nothing else holds them, holding Booleans as `u8` and characters as `i32`, because NumPy can write any bytes. Exact integers/fractions cross through native integers, not decimal strings. String/object arrays convert per item. Lists follow the shared import rule and dictionaries
|
|
235
|
+
Arrays retain native values. `.py` and `.np` make copies; NumPy is optional and lazy. The native `_Array` buffer export lends compact items read-only. An unbuilt structural copy whose read is affine (`Value::affine`) lends its source's items with strides, so windows reach NumPy without being built. Numeric buffers import with one copy through `rustymath_buffer::read_array`. `Value::imported_buffer` preserves supported item widths. The shared reader normalizes signed bytes, wider unsigned integers and foreign byte order. Sibling snapshots carry keys and names. A NumPy uint64 array containing a value above int64's range imports item by item as exact integers. `own()` moves compact items into a writable NumPy array where nothing else holds them, holding Booleans as `u8` and characters as `i32`, because NumPy can write any bytes. Exact integers/fractions cross through native integers, not decimal strings. String/object arrays convert per item. Python data converts in Rust: the session's `array` (`import` in `py/src/lib.rs`) walks nested lists through `rustymath_buffer::walk`, the walker rustymath's Python package uses, with a collector that nests a level whose items differ in shape. Lists follow the shared import rule, and dictionaries read as literals do. `rustymath_buffer::labels` is the one rule for a dict's keys and a frame's column labels, in both Python packages. A frame reads through `rustymath_buffer::frame` as a keyed vector of its columns, which `.df` turns back into a frame. `None` reads as NaN as an item. A bare `None` doesn't convert, so an operator given one returns `NotImplemented`. `syntax.py` wraps the native syntax tree with character spans and span-editing helpers.
|
|
226
236
|
|
|
227
|
-
`Array(existing)` creates an independent native handle. Assignment and `.keys`/`.names` setters replace the owner's handle without changing prior views or captured functions. Both Python packages
|
|
237
|
+
`Array(existing)` creates an independent native handle. Assignment and `.keys`/`.names` setters replace the owner's handle without changing prior views or captured functions. Both Python packages read written selectors as `structure::IndexPart` tokens through `rustymath/buffer/src/selection.rs`, and plan them with `structure::plan_parts`, the structural planner that `⌷` also uses. `structure::addressed_parts` routes source groups and expands `Rest` against the applicable frame. On a BPL array, Python's own kinds (`selection::native`: slices, keys, integers and lists of keys) decode in the buffer crate, Boolean masks select where they hold true, and other selectors become BPL values that decode as `⌷` decodes them (`Value::planned`). Pick paths select alone, as `⌷` reads them, keeping the written parts until the ending cell's geometry is known. `_Array.select` and `_Array.assign` use carrier-aware structural selection and writeback. Python assignment uses leading-axis broadcasting. Language writeback retains its own agreement.
|
|
228
238
|
|
|
229
239
|
Each `_Session` request waits for its evaluator mutex without the GIL, then evaluates on the caller's thread with the GIL released. A separate interrupt handle supports interruption from another thread. Signal polling briefly takes the GIL. Python input and optional streaming-output callbacks also cross at explicit boundary adapters. No Python numeric objects enter core values; arrays can be dropped on any thread without an unsafe Send implementation.
|
|
230
240
|
|
|
@@ -252,17 +262,17 @@ The playground and gallery load released assets from jsDelivr, or local `nbs/pla
|
|
|
252
262
|
|
|
253
263
|
`optimize.rs` implements `⇄` on `rustymath::optimize`. The left argument holds the options. When the method can use a derivative (none named, L-BFGS, Levenberg–Marquardt, CG or MINRES), one linearisation at the start (`derivative::linearized`) finds whether `∂` differentiates the function, and gives its value there. `Goal` evaluates the function at points in the start's layout for `minimize`. When the search runs L-BFGS, each value comes from a linearisation that `gradient` then transposes at the same point (`linearized_at`), so a value and its gradient run the function once. With `"solve":$t`, `Residual` is the `Mapping` that `solve` takes, or that `solve_affine` takes with `"linear":$t` as well. Where `∂` differentiates the function, `Residual` gives JVPs and vector–Jacobian products from one record at each point, or from the start's record for an affine function. At a later point where `∂` gives an UNSUPPORTED error, `Residual::jvp` declines, and rustymath takes forward differences for that Jacobian and later ones. A square linear system takes no products with the transpose, so it runs GMRES on A, not the normal equations. The function in option `precondition` gives the preconditioner.
|
|
254
264
|
|
|
255
|
-
CSV columns, JSON arrays and Python lists share `data::imported`: a non-fill finite float or any nonfinite float triggers float promotion when every number converts losslessly. Finite fills alone do not trigger it. Otherwise items keep their kinds. JSON objects
|
|
265
|
+
CSV columns, JSON arrays and Python lists share `data::imported`: a non-fill finite float or any nonfinite float triggers float promotion when every number converts losslessly. Finite fills alone do not trigger it. Otherwise items keep their kinds. JSON objects and Python dicts read as literals do, through `keyed::vector` and `Value::from_parts`. Binary data uses exact bytes. Writes validate before opening and create exclusively unless overwrite is explicit. CSV/JSON/XML exports use `•csv⁻¹`, `•json⁻¹` and `•xml⁻¹`.
|
|
256
266
|
|
|
257
267
|
`regex.rs` shares host regex state between match/replace native functions; hosts retain their own regex syntax. `xml.rs` represents keyed element trees and distinguishes XML escaping/validation from HTML raw script/style and void-element rules. SVG uses its own renderer. `image.rs` owns pictures, their options and animation timing, as plain pixel buffers. Its `codec` module decodes and encodes those buffers through ImageIO on Apple targets (`image/imageio.rs`) and through the `image` and `png` crates elsewhere (`image/codecs.rs`). Native/browser renderers use the MIME/byte formats their frontends support. `plot.rs` stores specs and draws SVG on demand; the renderer owns defaults/validation. Rendering options belong in their user pages and implementation comments.
|
|
258
268
|
|
|
259
|
-
`display.rs` owns plain/boxed/function display, elision and MIME rendering. Display settings affect implicit presentation, not returned values or `⍕`; explicit output prints all items. `•mime` calls a renderer with echo disabled and cancellation active. Failed implicit rendering falls back to text; interrupts/timeouts propagate. `canvas.rs` serializes drawing data and typed bytes; `canvas.js` and `nbs/driver.js` own browser playback. Keep formatting, serialization and rich output as separate contracts.
|
|
269
|
+
`display.rs` owns plain/boxed/function display, elision and MIME rendering. Display settings affect implicit presentation, not returned values or `⍕`; explicit output prints all items. Display and source text read the items, not their storage: `Value::shown_dtype` (`array/text.rs`) gives the dtype that compact storage of the items would take, by `storage::items_dtype`'s rule for items, which the shared `ₓ` or width marker, plain display's choice between brackets and a strand, the bracketed grid that plain display and `⍕` share (`display::table` and `display::bracketed`), a keyed table's corner and the boxed marker all read. `•mime` calls a renderer with echo disabled and cancellation active. Failed implicit rendering falls back to text; interrupts/timeouts propagate. `canvas.rs` serializes drawing data and typed bytes; `canvas.js` and `nbs/driver.js` own browser playback. Keep formatting, serialization and rich output as separate contracts.
|
|
260
270
|
|
|
261
271
|
## Tests and reference data
|
|
262
272
|
|
|
263
|
-
`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
|
|
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.
|
|
264
274
|
|
|
265
|
-
`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.
|
|
266
276
|
|
|
267
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.
|
|
268
278
|
|
|
@@ -283,7 +293,7 @@ Quarto renders saved outputs. `bpl-nb --save` updates notebook outputs without c
|
|
|
283
293
|
|
|
284
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.
|
|
285
295
|
|
|
286
|
-
`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.
|
|
287
297
|
|
|
288
298
|
## Release
|
|
289
299
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basedpl
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.63
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Requires-Dist: fastcore
|
|
@@ -8,6 +8,7 @@ Requires-Dist: fastship>=0.0.11 ; extra == 'dev'
|
|
|
8
8
|
Requires-Dist: fastws-cli>=0.0.26 ; extra == 'dev'
|
|
9
9
|
Requires-Dist: maturin>=1.9.4,<2.0 ; extra == 'dev'
|
|
10
10
|
Requires-Dist: pytest ; extra == 'dev'
|
|
11
|
+
Requires-Dist: pytest-timeout ; extra == 'dev'
|
|
11
12
|
Requires-Dist: numpy ; extra == 'dev'
|
|
12
13
|
Requires-Dist: pandas ; extra == 'dev'
|
|
13
14
|
Requires-Dist: ipython>=9.17.1 ; extra == 'dev'
|