basedpl 0.1.72__tar.gz → 0.1.74__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.72 → basedpl-0.1.74}/.github/workflows/ci.yml +2 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/.github/workflows/speed.yml +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/Cargo.lock +21 -19
- {basedpl-0.1.72 → basedpl-0.1.74}/Cargo.toml +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/DEV.md +18 -24
- {basedpl-0.1.72 → basedpl-0.1.74}/PKG-INFO +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/README.md +1 -1
- {basedpl-0.1.72/python/basedpl → basedpl-0.1.74/editors/jetbrains/BPL.tmbundle/Syntaxes}/bpl.tmLanguage.json +9 -5
- {basedpl-0.1.72/python/basedpl → basedpl-0.1.74/editors/jetbrains/BPL.tmbundle/Syntaxes}/hpl.tmLanguage.json +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.keylayout +1190 -264
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.keylayout +1143 -251
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.keylayout +1191 -212
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.keylayout +1190 -252
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.keylayout +1200 -235
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/vim/syntax/bpl.vim +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/README.md +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/layout.h +147 -35
- basedpl-0.1.74/nbs/bpl.xml +52 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/bqn.xml +27 -27
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/data.ipynb +1 -1
- basedpl-0.1.74/nbs/dyalog.xml +43 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/evaluation.qmd +4 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/prefs.bpl +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/brackets.qmd +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-star.qmd +2 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/obelus.qmd +4 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/slash.qmd +12 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs.qmd +3 -5
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/hpl.xml +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/index.ipynb +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/keyboard.qmd +4 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/llms.txt +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/magics.ipynb +31 -27
- basedpl-0.1.74/nbs/mathish.qmd +97 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/notebooks.ipynb +30 -26
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/numbers.qmd +51 -12
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground/hpl.tmLanguage.json +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/principles.ipynb +16 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/python.ipynb +130 -17
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/repl.qmd +4 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/scripts.ipynb +100 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/sidebar.yml +1 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/01_basics.ipynb +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/syntax.qmd +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/constants.qmd +2 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/explain.qmd +7 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/prefs.qmd +6 -6
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/terms.qmd +1 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/py/src/lib.rs +27 -11
- {basedpl-0.1.72 → basedpl-0.1.74}/pyproject.toml +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/__init__.py +22 -15
- {basedpl-0.1.72/editors/jetbrains/BPL.tmbundle/Syntaxes → basedpl-0.1.74/python/basedpl}/bpl.tmLanguage.json +9 -5
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/bpltests.py +117 -54
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/editors.py +39 -24
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/functions.py +7 -4
- {basedpl-0.1.72/editors/jetbrains/BPL.tmbundle/Syntaxes → basedpl-0.1.74/python/basedpl}/hpl.tmLanguage.json +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/input.js +10 -8
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/keyboards.py +8 -5
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/layout.json +5 -5
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/printing.py +2 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/windows_keyboard.py +5 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/worker.py +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/src/array/storage.rs +167 -95
- {basedpl-0.1.72 → basedpl-0.1.74}/src/array/text.rs +14 -11
- {basedpl-0.1.72 → basedpl-0.1.74}/src/array.rs +125 -55
- {basedpl-0.1.72 → basedpl-0.1.74}/src/batch.rs +228 -45
- {basedpl-0.1.72 → basedpl-0.1.74}/src/data.rs +24 -7
- {basedpl-0.1.72 → basedpl-0.1.74}/src/derivative.rs +24 -9
- {basedpl-0.1.72 → basedpl-0.1.74}/src/display.rs +26 -15
- {basedpl-0.1.72 → basedpl-0.1.74}/src/distribution.rs +13 -11
- {basedpl-0.1.72 → basedpl-0.1.74}/src/element.rs +20 -7
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/assign.rs +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/binder.rs +10 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/idioms.rs +17 -25
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/operators.rs +65 -24
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/session.rs +33 -7
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/tree.rs +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval.rs +8 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/src/fusion.rs +73 -40
- {basedpl-0.1.72 → basedpl-0.1.74}/src/js.rs +16 -14
- {basedpl-0.1.72 → basedpl-0.1.74}/src/keyed.rs +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/src/lib.rs +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/src/linear.rs +48 -12
- {basedpl-0.1.72 → basedpl-0.1.74}/src/number.rs +234 -112
- {basedpl-0.1.72 → basedpl-0.1.74}/src/pervasive.rs +303 -149
- {basedpl-0.1.72 → basedpl-0.1.74}/src/primitive/indexing.rs +93 -27
- {basedpl-0.1.72 → basedpl-0.1.74}/src/primitive/numeric.rs +30 -80
- {basedpl-0.1.72 → basedpl-0.1.74}/src/primitive/search.rs +49 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/src/primitive/structural.rs +7 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/src/primitive.rs +178 -64
- {basedpl-0.1.72 → basedpl-0.1.74}/src/reference.rs +143 -52
- {basedpl-0.1.72 → basedpl-0.1.74}/src/search.rs +74 -13
- {basedpl-0.1.72 → basedpl-0.1.74}/src/selection.rs +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/src/settings.rs +6 -6
- {basedpl-0.1.72 → basedpl-0.1.74}/src/syntax.rs +66 -43
- basedpl-0.1.74/src/timing.rs +199 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/transform.rs +19 -15
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/explain.rs +7 -5
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/highlighting.mjs +3 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/input.mjs +11 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/instructions.txt +3 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/README.md +25 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/april.bpl +2 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/core.bpl +196 -20
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/distributions.bpl +2 -2
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/dyalog.bpl +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/ngn.bpl +1 -1
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference.rs +27 -15
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/settings.rs +16 -1
- basedpl-0.1.74/tests/speed/README.md +13 -0
- basedpl-0.1.74/tests/speed/arrays.bpl +891 -0
- basedpl-0.1.74/tests/speed/calls.bpl +10 -0
- basedpl-0.1.74/tests/speed/images.bpl +62 -0
- basedpl-0.1.74/tests/speed/maps.bpl +253 -0
- basedpl-0.1.74/tests/speed/models.bpl +173 -0
- basedpl-0.1.74/tests/speed/structure.bpl +199 -0
- basedpl-0.1.74/tests/speed/tables.bpl +41 -0
- basedpl-0.1.74/tests/speed.rs +27 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_api.py +8 -6
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_basic.py +8 -8
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_bpltests.py +4 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_keylayout.py +8 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_repl.py +4 -3
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_windows_keyboard.py +7 -4
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/wasm-speed.mjs +8 -6
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/windows_keyboard.c +6 -3
- basedpl-0.1.72/nbs/bpl.xml +0 -51
- basedpl-0.1.72/nbs/dyalog.xml +0 -43
- basedpl-0.1.72/src/timing.rs +0 -237
- basedpl-0.1.72/tests/speed.rs +0 -26
- basedpl-0.1.72/tests/speed.txt +0 -752
- {basedpl-0.1.72 → basedpl-0.1.74}/.cargo/config.toml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/.gitattributes +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/.github/workflows/docs.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/.github/workflows/test.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/.gitignore +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/CONTRIBUTING.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/LICENSE +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/_config.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/_layouts/default.html +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/build.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/jetbrains/BPL.tmbundle/info.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/jetbrains/BPL.xml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/jetbrains/README.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-de.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.icns +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-de.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-de.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-de.txt +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-es.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.icns +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-es.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-es.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-es.txt +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-fr.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.icns +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-fr.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-fr.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-fr.txt +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-uk.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.icns +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-uk.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-uk.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-uk.txt +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-us.bundle/Contents/Info.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.icns +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-us.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-us.bundle/Contents/version.plist +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/macos/BasedPL-us.txt +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/vim/ftdetect/bpl.vim +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/build.ps1 +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/install.ps1 +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/keyboard.c +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/keyboard.def +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/editors/windows/keyboard.rc +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/index_files/figure-commonmark/cell-17-output-1.svg +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/index_files/figure-commonmark/cell-18-output-1.svg +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/index_files/figure-html/cell-17-output-1.svg +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/index_files/figure-html/cell-18-output-1.svg +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/LICENSE-april +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/README.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/array.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/dyalog.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/graph.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/numeric.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/power.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/regex.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/string.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/lib/tree.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/.gitignore +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/_quarto.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/arrays.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/assignment.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/bracket-types.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/cli.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/comparison.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/dfns.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/distributions.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/driver.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/dyalog.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/fonts/LICENSE-SAX2 +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/fonts/README.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/fonts/SAX2B.ttf +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/fonts/SAX2B.woff2 +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/fonts.css +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/attractor.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/boids.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/dragon.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/flow.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/mandelbrot.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/mandelbrot32.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/orbits.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/phyllotaxis.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery/reaction.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/gallery.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/getting-started.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/_metadata.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/alpha-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/alpha.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/at.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/backslash-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/backslash.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/braces.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/bullet.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-backslash.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-diaeresis.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-divide.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-slash.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-stile.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle-times.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/circle.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/colon.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/comma-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/comma.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/del-diaeresis.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/del-stile.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/del.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/delta-stile.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/diaeresis.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/diamond-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/diamond.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/domino.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/dot.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/down-arrow.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/down-shoe.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/down-tack.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/downstile.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/epsilon-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/epsilon.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/equal-underbar-slash.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/equal-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/equals.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/error-guard.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/exclamation.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/greater-than-or-equal.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/greater-than.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/hash.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/hydrant.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/infinity.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/inverted-question.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/iota-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/iota.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/jot-diaeresis.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/jot.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/lamp.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/left-arrow.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/left-shoe-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/left-shoe.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/left-tack.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/left-tail-arrow.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/less-than-or-equal.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/less-than.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/minus.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/not-equals.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/omega-underbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/omega.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/overbar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/parentheses.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/partial.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/pi.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/plus.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/quad-colon.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/quad-diamond.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/quad-equal.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/quad-jot.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/quad.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/question.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/quote.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/radical.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/rho.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/right-arrow-from-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/right-left-arrows.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/right-shoe.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/right-tack.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/right-tail-arrow.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/slash-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/squad.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/star-diaeresis.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/star.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/stile-tilde.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/stile.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/superscript-b.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/thorn.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/tilde-diaeresis.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/tilde.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/times.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/up-arrow.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/up-down-arrow.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/up-shoe.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/up-tack.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/upstile.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/vee-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/vee.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/wedge-bar.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/wedge.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs/zilde.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/glyphs-study.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/hanzi-notation-zh.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/hanzi-notation.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/indexing.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/introspection.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/keyed.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/modules.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/nbdev.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/overview.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/papers/aplwiki-arrays.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/papers/brickman-depth-1-scalars.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/papers/mercer-based-system.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground/bpl.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground/gallery.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground/monaco-worker.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground/page.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground/worker.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/playground.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/plot.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/processes.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/puppy.jpg +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/regex.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/strings.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/02_functions.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/03_operators.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/04_nested-arrays.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/05_searching-indexing.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/06_rearranging-arrays.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/study/07_numerical-tools.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/style.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/styles.css +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/_metadata.yml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/c.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/canvas.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/copy.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/csv.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/date.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/decompose.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/deflate.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/delay.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/detach.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/distribution.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/edge.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/element.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/ex.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/fetch.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/float.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/hash.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/host.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/image.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/index.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/js.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/json.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/literal.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/load.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/memory.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/metadata.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/mime.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/mkdir.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/nc.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/nget.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/nl.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/normalize.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/nput.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/path.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/plot.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/r.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/rand.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/readdir.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/remove.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/rename.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/signal.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/src.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/storage.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/svg.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/time.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/ucs.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/uuid.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/vfi.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system/xml.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/system-functions.qmd +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/web.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/nbs/xml.ipynb +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/package-lock.json +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/package.json +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/README.md +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/aplcart.jsonl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/april.jsonl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/bqn.jsonl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/core.jsonl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/dyalog.jsonl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/provenance/ngn.jsonl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/py/Cargo.toml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/py/build.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/_modidx.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/dyalog.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/font.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/fonts.css +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/ipython.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/keyboards.json +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/lb.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/notebook_runner.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/notebooks.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/reference.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/python/basedpl/syntax.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/rustfmt.toml +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/scripts/install-macos.sh +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/scripts/prep.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/agreement.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/canvas.js +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/canvas.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/csv.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/date.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/error.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/bindings.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/eval/dissect.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/execution.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/explain.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/files.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/fusion/blocks.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/host.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/host_web.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/image/codecs.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/image/imageio.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/image.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/inspection.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/json.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/name.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/number_theory.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/optimize.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/plot.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/polynomial.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/protocol.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/regex.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/symbols.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/system.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/src/xml.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/common/mod.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/conftest.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/core.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/derivatives.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/LICENSE-aplcart +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/LICENSE-april +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/LICENSE-bqn +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/LICENSE-bqncrate +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/LICENSE-dyalog +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/LICENSE-ngn +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/aplcart.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/bqn.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/graphics.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/lib.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/regex.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/static-int32.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/static.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/support/april.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/support/avl.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/support/redblack.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/support/sbst.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/reference/support/splay.bpl +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/scaling.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_glyphs.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_graphics.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_instructions.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_ipython.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_kernel.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_notebooks.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_reference.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/test_worker.py +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/units.rs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/wasm-pkg.mjs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/tests/wasm.mjs +0 -0
- {basedpl-0.1.72 → basedpl-0.1.74}/wheel/data/share/jupyter/kernels/bpl/kernel.json +0 -0
|
@@ -30,7 +30,7 @@ jobs:
|
|
|
30
30
|
run: pip install 'fastws-cli>=0.0.25' && ${{ env.STAGE_BPL }}
|
|
31
31
|
- uses: PyO3/maturin-action@v1
|
|
32
32
|
with:
|
|
33
|
-
args: --profile dist --no-default-features --out dist -i python3.11 -i python3.12 -i python3.13
|
|
33
|
+
args: --profile dist --no-default-features --compression-level 9 --out dist -i python3.11 -i python3.12 -i python3.13
|
|
34
34
|
manylinux: auto
|
|
35
35
|
# This runs inside the manylinux container, whose old glibc lets the binary run on older Linux distributions.
|
|
36
36
|
before-script-linux: export PATH="/opt/python/cp311-cp311/bin:$PATH" && python3.11 -m pip install 'fastws-cli>=0.0.25' && ${{ env.STAGE_BPL }}
|
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
- name: Time the release build
|
|
39
39
|
continue-on-error: true
|
|
40
40
|
timeout-minutes: 20
|
|
41
|
-
run: bin/${{ matrix.binary }} --costs tests/speed
|
|
41
|
+
run: bin/${{ matrix.binary }} --costs tests/speed
|
|
42
42
|
- uses: actions/upload-artifact@v7
|
|
43
43
|
with:
|
|
44
44
|
name: wheels-${{ matrix.os }}
|
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
python-version: '3.12'
|
|
17
17
|
# This job times the `bpl` that releases ship, which `cargo stage --profile dist` builds, as the `Release` workflow does. `bpl --costs` prints every case's cost and budget for `basedpl.bpltests.logged_costs`. A case over its budget doesn't fail it. The job builds without a cache. The `Test` workflow's caches hold only test-profile builds.
|
|
18
18
|
- run: pip install 'fastws-cli>=0.0.25' && cargo stage --profile dist
|
|
19
|
-
- run: wheel/scripts/bpl --costs tests/speed
|
|
19
|
+
- run: wheel/scripts/bpl --costs tests/speed
|
|
20
20
|
# `bpl-tests thread_scaling` times a large product, a 512×512 SVD and Hermitian eigendecomposition, a stack of QR decompositions and a large elementwise function on one thread and on the runner's cores, and fails when one speeds up less than 1.5 times. Speed budgets are single-thread measurements, so this is the check of multithreaded speed. It comes last, so that a failure here still leaves every cost logged.
|
|
21
21
|
- run: pip install -e . && bpl-tests thread_scaling --bpl wheel/scripts/bpl
|
|
22
22
|
|
|
@@ -93,7 +93,7 @@ checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
|
|
|
93
93
|
|
|
94
94
|
[[package]]
|
|
95
95
|
name = "basedpl"
|
|
96
|
-
version = "0.1.
|
|
96
|
+
version = "0.1.74"
|
|
97
97
|
dependencies = [
|
|
98
98
|
"base64 0.23.1",
|
|
99
99
|
"bytemuck",
|
|
@@ -137,20 +137,21 @@ dependencies = [
|
|
|
137
137
|
|
|
138
138
|
[[package]]
|
|
139
139
|
name = "basedpl-cli"
|
|
140
|
-
version = "0.1.
|
|
140
|
+
version = "0.1.74"
|
|
141
141
|
dependencies = [
|
|
142
142
|
"async-trait",
|
|
143
143
|
"basedpl",
|
|
144
144
|
"ctrlc",
|
|
145
145
|
"kernmini",
|
|
146
146
|
"rustyline",
|
|
147
|
+
"rustymath",
|
|
147
148
|
"serde",
|
|
148
149
|
"serde_json",
|
|
149
150
|
]
|
|
150
151
|
|
|
151
152
|
[[package]]
|
|
152
153
|
name = "basedpl-py"
|
|
153
|
-
version = "0.1.
|
|
154
|
+
version = "0.1.74"
|
|
154
155
|
dependencies = [
|
|
155
156
|
"basedpl",
|
|
156
157
|
"num-bigint",
|
|
@@ -165,10 +166,11 @@ dependencies = [
|
|
|
165
166
|
|
|
166
167
|
[[package]]
|
|
167
168
|
name = "basedpl-wasm"
|
|
168
|
-
version = "0.1.
|
|
169
|
+
version = "0.1.74"
|
|
169
170
|
dependencies = [
|
|
170
171
|
"basedpl",
|
|
171
172
|
"js-sys",
|
|
173
|
+
"serde_json",
|
|
172
174
|
"talc",
|
|
173
175
|
"wasm-bindgen",
|
|
174
176
|
]
|
|
@@ -857,9 +859,9 @@ dependencies = [
|
|
|
857
859
|
|
|
858
860
|
[[package]]
|
|
859
861
|
name = "json5"
|
|
860
|
-
version = "1.3.
|
|
862
|
+
version = "1.3.4"
|
|
861
863
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
862
|
-
checksum = "
|
|
864
|
+
checksum = "1628f14e201e5d6683248a22736547a083c2c176652d65b1068be73dab213a28"
|
|
863
865
|
dependencies = [
|
|
864
866
|
"serde",
|
|
865
867
|
"ucd-trie",
|
|
@@ -1361,9 +1363,9 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
|
1361
1363
|
|
|
1362
1364
|
[[package]]
|
|
1363
1365
|
name = "roxmltree"
|
|
1364
|
-
version = "0.21.
|
|
1366
|
+
version = "0.21.2"
|
|
1365
1367
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1366
|
-
checksum = "
|
|
1368
|
+
checksum = "9da7f59328b09405b181fee1018925fad50f157afb43c0c0f5c522c256dd5907"
|
|
1367
1369
|
dependencies = [
|
|
1368
1370
|
"memchr",
|
|
1369
1371
|
]
|
|
@@ -1413,9 +1415,9 @@ dependencies = [
|
|
|
1413
1415
|
|
|
1414
1416
|
[[package]]
|
|
1415
1417
|
name = "rustymath"
|
|
1416
|
-
version = "0.1.
|
|
1418
|
+
version = "0.1.49"
|
|
1417
1419
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1418
|
-
checksum = "
|
|
1420
|
+
checksum = "e9aedcee908443b05f25913ad641d665c8388e8de7aca5f5aa16d10eeffec475"
|
|
1419
1421
|
dependencies = [
|
|
1420
1422
|
"foldhash",
|
|
1421
1423
|
"half",
|
|
@@ -1434,9 +1436,9 @@ dependencies = [
|
|
|
1434
1436
|
|
|
1435
1437
|
[[package]]
|
|
1436
1438
|
name = "rustymath-buffer"
|
|
1437
|
-
version = "0.1.
|
|
1439
|
+
version = "0.1.49"
|
|
1438
1440
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1439
|
-
checksum = "
|
|
1441
|
+
checksum = "f4c19ddeaf8f211645269dfb77fd01c26b4a4e268f150ea473677fee942c7ee1"
|
|
1440
1442
|
dependencies = [
|
|
1441
1443
|
"pyo3",
|
|
1442
1444
|
"rustymath",
|
|
@@ -1581,9 +1583,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
|
|
1581
1583
|
|
|
1582
1584
|
[[package]]
|
|
1583
1585
|
name = "smallvec"
|
|
1584
|
-
version = "1.16.
|
|
1586
|
+
version = "1.16.4"
|
|
1585
1587
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1586
|
-
checksum = "
|
|
1588
|
+
checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8"
|
|
1587
1589
|
|
|
1588
1590
|
[[package]]
|
|
1589
1591
|
name = "socket2"
|
|
@@ -1814,9 +1816,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|
|
1814
1816
|
|
|
1815
1817
|
[[package]]
|
|
1816
1818
|
name = "uuid"
|
|
1817
|
-
version = "1.
|
|
1819
|
+
version = "1.29.0"
|
|
1818
1820
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1819
|
-
checksum = "
|
|
1821
|
+
checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514"
|
|
1820
1822
|
dependencies = [
|
|
1821
1823
|
"atomic",
|
|
1822
1824
|
"getrandom",
|
|
@@ -1850,9 +1852,9 @@ dependencies = [
|
|
|
1850
1852
|
|
|
1851
1853
|
[[package]]
|
|
1852
1854
|
name = "walrus"
|
|
1853
|
-
version = "0.27.
|
|
1855
|
+
version = "0.27.3"
|
|
1854
1856
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1855
|
-
checksum = "
|
|
1857
|
+
checksum = "5691aeb3546554822fe2c13d63149c26a027cd07d900a72c7c7f37f4321bfaea"
|
|
1856
1858
|
dependencies = [
|
|
1857
1859
|
"anyhow",
|
|
1858
1860
|
"gimli",
|
|
@@ -2086,7 +2088,7 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
|
|
|
2086
2088
|
|
|
2087
2089
|
[[package]]
|
|
2088
2090
|
name = "xtask"
|
|
2089
|
-
version = "0.1.
|
|
2091
|
+
version = "0.1.74"
|
|
2090
2092
|
dependencies = [
|
|
2091
2093
|
"anyhow",
|
|
2092
2094
|
"rustymath",
|
|
@@ -5,14 +5,14 @@ members = ["py"]
|
|
|
5
5
|
join_comments = true
|
|
6
6
|
|
|
7
7
|
[workspace.package]
|
|
8
|
-
version = "0.1.
|
|
8
|
+
version = "0.1.74"
|
|
9
9
|
edition = "2024"
|
|
10
10
|
rust-version = "1.98"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
|
|
13
13
|
[workspace.dependencies]
|
|
14
|
-
rustymath = { version = ">=0.1.
|
|
15
|
-
rustymath-buffer = ">=0.1.
|
|
14
|
+
rustymath = { version = ">=0.1.49, <1", default-features = false }
|
|
15
|
+
rustymath-buffer = ">=0.1.49, <1"
|
|
16
16
|
pyo3 = ">=0.29.2, <1"
|
|
17
17
|
pyo3-build-config = ">=0.29.2, <1"
|
|
18
18
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Development
|
|
2
2
|
|
|
3
|
-
Keep the language concise to write, simple to read and consistent to understand. A design rule is a plan on trial. Discuss it when applying it makes a useful expression harder to read, removes something expressible or requires another special case. APL familiarity and compatibility are not costs in that decision. Change callers with an API change instead of adding compatibility layers.
|
|
3
|
+
Keep the language concise to write, simple to read and consistent to understand. A design rule is a plan on trial. Discuss it when applying it makes a useful expression harder to read, removes something expressible or requires another special case. APL familiarity and compatibility are not costs in that decision. Change callers with an API change instead of adding compatibility layers. Give each kind of thing the general path rather than a separate one of its own. A system name, for example, resolves to a function and compiles as a glyph does.
|
|
4
4
|
|
|
5
|
-
Speed and simplicity come before edge cases no real user meets. Follow IEEE, Rust and CPU behaviour where it gives a reasonable result.
|
|
5
|
+
Speed and simplicity come before edge cases no real user meets. Follow IEEE, Rust and CPU behaviour where it gives a reasonable result. Precision follows the rules in the "Overview" of rustymath's `DEV.md`.
|
|
6
6
|
|
|
7
7
|
A form with a reasonable meaning gives a result, not an error. A result that would be a bug in some programs, with no error, is acceptable when it buys useful behaviour or speed. Negative positions count from the end in every selection, as in Python, even though `x.[i-1]` at `i=0` then reads the last item. `⌈` beside NaN gives NaN or the other argument, whichever its kernel gives. Jeremy settled negative positions on 18 October 2026, after the question had come up repeatedly.
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ cargo test
|
|
|
18
18
|
pytest -q
|
|
19
19
|
```
|
|
20
20
|
|
|
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.
|
|
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. From a kernel, `fastws.cargo.run_tests(root, *args)` runs `cargo test` and returns the build's compiler messages and each test binary's results. 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.
|
|
22
22
|
|
|
23
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.
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ When another agent's unfinished edits stop the shared tree compiling, run `cargo
|
|
|
26
26
|
|
|
27
27
|
An already-running Python process retains its loaded extension. In a kernel, use `from basedpl.worker import fresh; fresh(code)` to check the installed `bpl` in a fresh worker instead of restarting the kernel. A BPL error raises `BplError`. `fresh(code, bpl=PATH)` runs a saved copy of `bpl`, such as the baseline described below. Check one expression and read its result before building on it. `basedpl.bpltests.check_file` and `check_page` check reference files and documentation through the worker without building Rust. With `bpl=PATH`, they check a saved copy without installing it.
|
|
28
28
|
|
|
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. `rustymath::timing::COPIES` stores the copy time of each machine that runs the speed tests, by its CPU, the item's size and the number of items, at the slower end of what that copy normally takes, for copies whose source and destination fit in cache, 64 MiB together (`CACHED_BYTES`). A copy timed beside each case varied more than 3 times on CI's runner, where the functions' own times didn't, so stored times keep that noise out of every cost. A larger copy runs at the speed of memory, which a shared runner varies by up to 2 times between runs, and the cases of that size vary with it. The test measures such a copy once in each run. It also measures a cached size with no entry once, and prints a line to add to `COPIES`. The browser build has entries of its own, for its copy under the JavaScript engine. It can't read the CPU's name, and `tests/wasm-pkg.mjs` passes it the name that Node reads. Each case's line in a log ends with its time for each item, which `logged_costs` keeps in each row, and the log has a copy line for each size of data, which it reads into its result's `copies`. Budgets are single-thread measurements. `thread_scaling()` checks multithreaded speed: it times a large product, a 512×512 SVD and Hermitian eigendecomposition, a stack of QR decompositions and a large elementwise function on one thread and on the machine's cores, and fails when one speeds up less than 1.5 times. Accelerate's GESDD and SYEVD run on one thread whatever its threading setting. On macOS, where Accelerate computes the product, the SVD and the Hermitian eigendecomposition, those three cases need only the speedups in `_ACCELERATED_LEAST`. The manual `Speed` workflow runs it. `speed_costs()` reads the cases in `tests/speed
|
|
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. `rustymath::timing::COPIES` stores the copy time of each machine that runs the speed tests, by its CPU, the item's size and the number of items, at the slower end of what that copy normally takes, for copies whose source and destination fit in cache, 64 MiB together (`CACHED_BYTES`). A copy timed beside each case varied more than 3 times on CI's runner, where the functions' own times didn't, so stored times keep that noise out of every cost. A larger copy runs at the speed of memory, which a shared runner varies by up to 2 times between runs, and the cases of that size vary with it. The test measures such a copy once in each run. It also measures a cached size with no entry once, and prints a line to add to `COPIES`. The browser build has entries of its own, for its copy under the JavaScript engine. It can't read the CPU's name, and `tests/wasm-pkg.mjs` passes it the name that Node reads. Each case's line in a log ends with its time for each item, which `logged_costs` keeps in each row, and the log has a copy line for each size of data, which it reads into its result's `copies`. Budgets are single-thread measurements. `thread_scaling()` checks multithreaded speed: it times a large product, a 512×512 SVD and Hermitian eigendecomposition, a stack of QR decompositions and a large elementwise function on one thread and on the machine's cores, and fails when one speeds up less than 1.5 times. Accelerate's GESDD and SYEVD run on one thread whatever its threading setting. On macOS, where Accelerate computes the product, the SVD and the Hermitian eigendecomposition, those three cases need only the speedups in `_ACCELERATED_LEAST`. The manual `Speed` workflow runs it. `speed_costs()` reads the cases in `tests/speed/*.bpl`. `cases=` selects expressions, `wasm=DIR` selects a browser build, `bpl=PATH` selects another native `bpl`, such as a saved copy, `native=True` times rustymath's own linear algebra, which dev builds compile in, and `prefs=` runs BPL before each section's header, such as `•prefs ["kinds":"static"]`. `logged_costs(log)` reads CI output from its text or a file. `cargo_costs(path)` runs either project's Rust speed test, and `pytest_costs(path)` runs rustymath's Python speed test.
|
|
30
30
|
|
|
31
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 an expression, such as `k(⌈/⊢)⌸a`, run once per step inside `{case ⋄ ⍵}⍣N⊢0`. That dfn's own call adds about 1,900 instructions a step. A case that names `N` makes its own calls instead, such as `{⍵}⍣N⊢0`, which makes one dfn call a step. Such a case must make one call per step: 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 four values of `N`. For each pair of successive values, it divides the difference in instructions retired by the difference in `N`, which cancels startup and `setup=`, and it reports the median of those three slopes. The median drops a one-off cost that starts once `N` passes some size, because such a cost falls between only one pair. `≢•ucs N⍴"ab" "cde"` has one: it retires about 5×10⁶ more instructions from about 131,350 items on. Every value of `N` lies past the warm-up, from a rough count at 1,000 steps, because a case that allocates an array at each step retires extra instructions over its first steps while the allocator settles. Each process pays a different warm-up, up to about 5×10⁶ instructions, so successive values of `N` lie 5×10⁸ instructions apart, where that difference moves a slope by under 1%. `counts=` sets two or more values instead. It reads `/usr/bin/time -l` on macOS and `perf stat` on Linux, and `bpl=PATH` counts a saved copy. A case whose result stays pending, such as large windows or a transpose, counts making the pending copy, not the copy: `3↕v` retires about 12,000 instructions a step. `force=True` computes each step's result in full, through an indexed write, for any result of rank 1 or more: `3↕v` then counts the copy itself, about 9 million instructions a step. A join computes at once and needs no `force`.
|
|
32
32
|
|
|
@@ -34,33 +34,27 @@ Costs in copies can't show a per-call change of a few percent, because code layo
|
|
|
34
34
|
|
|
35
35
|
`profile(case)` shows where a case's instructions go, by function, on macOS. It takes a case, and `force=`, as `instructions` does. A fresh process repeats the case on one thread while `sample` counts how often each function is at the top of the main thread's stack. A function's share of those samples, times the build's count from `instructions`, estimates its instructions per step. The estimate assumes every function retires instructions at the same rate. When a count moves, `profile_diff(case, base)` shows which functions moved it, from those estimates for both builds. A function that one build inlines and the other calls out of line appears under one build alone. Run them before reading machine code. `base` is a saved copy, and `bpl=PATH` sets the build to profile, the installed one by default.
|
|
36
36
|
|
|
37
|
-
`bpl-tests NAME ARGUMENT...` runs one of these functions from the shell and prints its result: `check_file`, `check_page`, `time_cases`, `instructions`, `instruction_budgets`, `profile`, `profile_diff`, `speed_costs`, `thread_scaling`, `cargo_costs`, `pytest_costs`, `compare_costs` or `wasm_test`.
|
|
37
|
+
`bpl-tests NAME ARGUMENT...` runs one of these functions from the shell and prints its result: `check_file`, `check_page`, `time_cases`, `instructions`, `instruction_budgets`, `profile`, `profile_diff`, `disasm`, `speed_costs`, `thread_scaling`, `cargo_costs`, `pytest_costs`, `compare_costs` or `wasm_test`. 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. Called in a kernel, the same functions return Python objects, such as the rows that `compare_costs` reads.
|
|
38
38
|
|
|
39
|
-
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
|
|
39
|
+
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 PATH` times a `.bpl` file or a directory of them 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% since the run before. `compare_costs(before, after)` lists both, from two runs' logs or from the rows that `speed_costs` and the other timing functions give. It measures each change on times per item where both runs give them, so a change to `COPIES` doesn't show as one. Every log names its CPU in its copy lines. 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.
|
|
40
40
|
|
|
41
|
-
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
|
|
41
|
+
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 `⍝⍝:` footer in a BPL speed 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 for Node on CI's x86 runner. 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 a BPL speed file or directory, or one of Rustymath's table-format files, `tests/speed.txt` or `tests/speed_python.txt`.
|
|
42
42
|
|
|
43
|
-
`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`. A faster route that code considered and didn't take is a decline (`declined`), named by its route and reason, as in `fusion: an exact argument`. A case needn't name a decline, because each one explains another event, but a `gap` line can name one to record why the fast route was refused. Code in either repository reports a decline through `rustymath::events::declined`, which costs one atomic load unless `•explain` runs.
|
|
43
|
+
`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`. A faster route that code considered and didn't take is a decline (`declined`), named by its route and reason, as in `fusion: an exact argument`. A case needn't name a decline, because each one explains another event, but a `gap` line can name one to record why the fast route was refused. Code in either repository reports a decline through `rustymath::events::declined`, which costs one atomic load unless `•explain` runs. `⍝⍝ 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.
|
|
44
44
|
|
|
45
45
|
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.
|
|
46
46
|
|
|
47
|
-
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
|
|
47
|
+
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 a kernel, run `shutil.copy(basedpl.worker.INSTALLED_BPL, '/tmp/<prefix>_bpl')`. In the shell, run `cp "$(command -v bpl)" /tmp/<prefix>_bpl`: the installed `bpl` is the one on the venv's `PATH`. 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. Compare the two builds' times per item, which `time_cases` prints in picoseconds. A build from before a change to `rustymath::timing::COPIES` divides its costs by a different copy. 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.
|
|
48
48
|
|
|
49
|
-
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, `check_file`, `check_page`, `bpl-nb` 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
|
|
49
|
+
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, `check_file`, `check_page`, `bpl-nb` 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 a kernel process. Never coordinate timings by hand. A hold that outlasts its call blocks the timings that later calls launch. Native timings run on one thread and request user-interactive macOS QoS, which favours the performance cores. QoS is not CPU affinity.
|
|
50
50
|
|
|
51
51
|
Run `cargo wasm` during development only for browser work. Agents use `cargo wasm --out DIR`, then run the browser tests against that build with `basedpl.bpltests.wasm_test(DIR)` for `tests/wasm.mjs` and `wasm_test(DIR, speed=True)` for `tests/wasm-speed.mjs`. That speed test fails on a wasm budget only on Linux x86-64, CI's platform. On any other host it prints every cost and marks each case still over its budget after the retries, as `bpl --costs` does. This avoids replacing a module another agent is using. For other edits under `cfg(web)` or `host_web.rs`, check compilation with `cargo cs -p basedpl-wasm --target wasm32-unknown-unknown`, which checks the browser wrapper crate together with basedpl's browser code. `cargo cs` alone compiles neither.
|
|
52
52
|
|
|
53
|
-
###
|
|
53
|
+
### Machine code
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
`bpl-tests disasm PATTERN` shows the machine code of the function whose demangled name matches the regex `PATTERN`, read from the installed `bpl` with `objdump`. `--bpl PATH` reads a saved copy instead. Where several functions match, it lists their names. A function that is always inlined has no code of its own. Read its callers instead.
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
CARGO_INCREMENTAL=0 CC_x86_64_unknown_linux_gnu=clang cargo build --lib --release --target x86_64-unknown-linux-gnu --target-dir /tmp/aai-ws-x86 -p basedpl
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
In rustymath, use `-p rustymath`. The target is Linux because macOS builds leave out rustymath's native linear algebra kernels. That target is installed here. `-p` builds only the library, because the Python extension crates can't be built for Linux on this Mac. `CC_x86_64_unknown_linux_gnu=clang` lets Apple's `clang` assemble the x86-64 source in basedpl's `psm` dependency, because this Mac has no `x86_64-linux-gnu-gcc`. Don't move that setting into `.cargo/config.toml`. CI's Linux release builds also read that file, and their manylinux container has no `clang`. The build matches CI's `test` profile in its x86-64 flags and optimization settings. CI turns off the profile's incremental compilation with `CARGO_INCREMENTAL=0`. The command does the same, to split code into compilation units as CI does. Run it only to answer an x86-code question. It doesn't take the timing lock and can disturb timings running alongside it.
|
|
62
|
-
|
|
63
|
-
Read the newest `lib<crate>-<hash>.rlib` under `/tmp/aai-ws-x86/x86_64-unknown-linux-gnu/release/deps` with `objdump -d -r --no-show-raw-insn --disassemble-symbols=NAME`. `-r` identifies called functions. `objdump` warns for each archive object without that symbol. `-C` matches demangled names but splits them at commas; for a generic name containing a comma, get its mangled name from `nm` and omit `-C`. Generic code belongs to the crate that instantiates it. Don't use `--emit asm`: the resulting codegen-unit arrangement can inline differently from the build being inspected.
|
|
57
|
+
`--x86` shows the x86-64 code that CI and Linux run. It first builds basedpl's library and the rustymath library it links for Linux x86-64, into `/tmp/aai-ws-x86`, holding the timing lock shared. Where an unfinished edit stops basedpl compiling, it reads rustymath's library alone, and its output says so first. After a change, that build takes minutes. Use it only to answer an x86-code question. The target is Linux because macOS builds leave out rustymath's native linear algebra kernels. Only the libraries build, because the Python extension crates can't be built for Linux on this Mac. Their `release` profile matches CI's `test` profile in its x86-64 flags and optimization settings. The build sets `CC_x86_64_unknown_linux_gnu=clang` for itself. Don't move that setting into `.cargo/config.toml`. CI's Linux release builds also read that file, in a manylinux container that has no `clang`. Don't use `--emit asm`. A build with it splits code into other codegen units and inlines differently.
|
|
64
58
|
|
|
65
59
|
## Workspace, builds and CI
|
|
66
60
|
|
|
@@ -186,11 +180,11 @@ Float operations compute at the wider operand width. Exact operands round to the
|
|
|
186
180
|
|
|
187
181
|
Floats use IEEE NaN, infinity and signed zero. Comparison treats NaN as unequal; match/search treat it as one value, and grade puts it last. Exact arithmetic involving division by zero can produce those float values. Floor/ceiling retain an exact operand beside infinity. Beside NaN the language leaves their result open: NaN or the other argument, varying by platform. Their folds, scans, windows, products and repeated writes give NaN or the maximum or minimum of the items that aren't NaN, never another number, by the rule in rustymath's `Folds` doc. A loop that folds by them either passes its running result as the right argument, which `rustymath::reduce::maximum` keeps beside NaN, or folds through rustymath's `Max` and `Min`, as `Dyad::extremum` does. Monadic floor/ceiling/sign turn whole finite results into exact integers, including big integers; nonfinite results remain floats. Use `Number::float(value, width)` and explicit-width array construction outside `number.rs` instead of implicit f64 conversion.
|
|
188
182
|
|
|
189
|
-
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.
|
|
183
|
+
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`. Comparisons, `⌈ ⌊` and bitwise functions compute at their arguments' storage width instead, where their results are the same at every width (`pervasive::first_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.
|
|
190
184
|
|
|
191
185
|
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.
|
|
192
186
|
|
|
193
|
-
|
|
187
|
+
`Numeric::mathish_at(width)` owns Mathish eligibility: the preference must be on, kinds dynamic and the calculation ordinary exact, f64 or complex128. Fixed-integer operations are excluded even when computing at f64. Kernels select their numerical objects before the loop. Mathish comparison tolerance is `1E-14`. f32/f16 compare exactly. Fixed-point convergence uses four ulps at those widths and `1E-14` at f64, independently of Mathish. Index/count/Boolean/character-offset conversion uses `near_integer` with the fixed default tolerance. The numerical objects come from rustymath. Use independent inside/outside-tolerance tests with exact/mixed controls rather than language comparison as its own oracle.
|
|
194
188
|
|
|
195
189
|
`search.rs` selects compact exact or tolerant backends. Exact integer/Boolean/character storage uses keys; float searches use their width. Integer haystacks accept the whole-number shortcut only for exactly whole float needles. Tolerant indexing validates whole-key matches unless the haystack is exactly whole and falls back to buckets on mismatch. Classification intentionally chains tolerance through sorted runs, so it need not match every member to one representative. Other cells use exact hashes or first-number buckets with `Value::matches` confirmation, falling back to pairwise comparison where indexing is unsuitable. Grade is stable. Position buffers use u32 and become integer storage without another pass. `⍷` and monadic Key take each class's positions from `search::class_positions`, which keeps a class's own buffer for 32-bit positions and copies narrower ones once from the shared buffer. Dyadic Key selects rows through `Groups::each` slices. Key's group-fold idiom folds through `search::numbered`'s class numbers. Where `fold_groups` declines, Key builds the positions from those numbers. Key with the operand `≢⊢`, which `≢∘⊢` also builds, counts its classes through `search::class_counts` and builds no positions.
|
|
196
190
|
|
|
@@ -222,7 +216,7 @@ Ordinary pervasive kernels also read pending copies through their maps. `fusion:
|
|
|
222
216
|
|
|
223
217
|
`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 `Stacked::inverse`, or by exact row reduction for exact matrices. `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.
|
|
224
218
|
|
|
225
|
-
`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 random draws to their own code. It runs any other system function once for each cell, on that cell's arguments, as the function runs once for each item of an argument that holds several, and joins the cells' results into one batch (`batch::system`, `batch::each_cell`). `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 the code in a system function that acts (`Effect::Acts`, through `Context::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.
|
|
219
|
+
`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 random draws to their own code. It runs any other system function once for each cell, on that cell's arguments, as the function runs once for each item of an argument that holds several, and joins the cells' results into one batch (`batch::system`, `batch::each_cell`). `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 the code in a system function that acts (`Effect::Acts`, through `Context::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 map inside the run widens the run instead of beginning another, where the run is the innermost level (`batch::Entry::Widen`). The widening is a case with no definition, whose frame is the run's frame followed by the map's. The run's batches among the map's arguments lay over that frame (`batch::laid_over`), and a binding made before the widening lays over it when code reads it (`Session::read_binding`). A widened run that stops, or an Each whose results are arrays, falls back to calling the map's operand once for each of its cells inside 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.
|
|
226
220
|
|
|
227
221
|
Rustymath owns numeric folds, scans, adjacent pairs, grouped reductions and integer bounds. Basedpl selects kernels, tolerance, seeds, storage widths and exact fallbacks. Which reduction folds each primitive comes from rustymath's `facts!` table, through `pervasive::folds` and `truth_fold`, and so do the object by whose rule each takes characters and the comparison objects that `with_comparison!` makes. 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.
|
|
228
222
|
|
|
@@ -288,9 +282,9 @@ CSV columns, JSON arrays and Python lists share `data::imported`: a non-fill fin
|
|
|
288
282
|
|
|
289
283
|
`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.
|
|
290
284
|
|
|
291
|
-
`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 four times, with the `batch` pref off, then on, then on with fusion's small sizes, then on with its code as the body of a dfn that one session calls twice (`twice`), and each run starts from the defaults and the file's header. The fourth run checks that a dfn's second call, which runs the statements its first call recorded, gives the first call's value, storage kind, error and output. Code that can't be a dfn's body skips it. `tests/reference.rs` checks the cases in a child process of itself for each core, and Python's `check_file` in a worker for each core, because a process evaluates one case at a time. `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.
|
|
285
|
+
`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. An optional `⍝⍝ setup` supplies shared definitions, initialized independently for each run and its expectation. A section's inline `•prefs` suffix runs before setup. Each case runs four times, with the `batch` pref off, then on, then on with fusion's small sizes, then on with its code as the body of a dfn that one session calls twice (`twice`), and each run starts from the defaults and the file's header. The fourth run checks that a dfn's second call, which runs the statements its first call recorded, gives the first call's value, storage kind, error and output. Code that can't be a dfn's body skips it. `tests/reference.rs` checks the cases in a child process of itself for each core, and Python's `check_file` in a worker for each core, because a process evaluates one case at a time. `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.
|
|
292
286
|
|
|
293
|
-
`tests/scaling.rs` measures time/allocation growth and result-size allocation budgets. `tests/speed.rs` reads native/browser budgets from `speed
|
|
287
|
+
`tests/scaling.rs` measures time/allocation growth and result-size allocation budgets. `tests/speed.rs` reads native/browser budgets from `speed/*.bpl` 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.
|
|
294
288
|
|
|
295
289
|
## Documentation and generated assets
|
|
296
290
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basedpl
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.74
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Requires-Dist: fastcore
|
|
@@ -15,7 +15,7 @@ Requires-Dist: ipython>=9.17.1 ; extra == 'dev'
|
|
|
15
15
|
Requires-Dist: nbdev>=3.3.24 ; extra == 'dev'
|
|
16
16
|
Requires-Dist: conkernelclient>=0.0.23 ; extra == 'dev'
|
|
17
17
|
Requires-Dist: pillow ; extra == 'dev'
|
|
18
|
-
Requires-Dist: rustymath>=0.1.
|
|
18
|
+
Requires-Dist: rustymath>=0.1.49 ; extra == 'dev'
|
|
19
19
|
Provides-Extra: dev
|
|
20
20
|
License-File: LICENSE
|
|
21
21
|
Summary: BasedPL, the Based-array Programming Language, is an APL-derived array language, borrowing ideas from J and BQN, with an emphasis on simple, consistent notation.
|
|
@@ -118,7 +118,7 @@ For APL users, some key differences are:
|
|
|
118
118
|
- **Exact integers and rationals** alongside approximate real and complex numbers.
|
|
119
119
|
- Dfns, trains and operators, with additions such as Under, iteration histories, windows and function arrays.
|
|
120
120
|
|
|
121
|
-
Positions and axes count from 0, as in BQN and Python.
|
|
121
|
+
Positions and axes count from 0, as in BQN and Python. Default [Mathish mode](https://answerdotai.github.io/basedpl/numbers.html#mathish-mode) uses relative tolerance `1E¯14` for 64-bit comparisons and defines `0÷0=0` for [Mathish types](https://answerdotai.github.io/basedpl/terms.html#term-mathish-types). See the [language principles](https://answerdotai.github.io/basedpl/principles.html) for the language design, the [glyph reference](https://answerdotai.github.io/basedpl/glyphs.html) for Dyalog differences and [Arrays](https://answerdotai.github.io/basedpl/arrays.html) for the array model.
|
|
122
122
|
|
|
123
123
|
### Numbers
|
|
124
124
|
|
|
@@ -88,7 +88,7 @@ For APL users, some key differences are:
|
|
|
88
88
|
- **Exact integers and rationals** alongside approximate real and complex numbers.
|
|
89
89
|
- Dfns, trains and operators, with additions such as Under, iteration histories, windows and function arrays.
|
|
90
90
|
|
|
91
|
-
Positions and axes count from 0, as in BQN and Python.
|
|
91
|
+
Positions and axes count from 0, as in BQN and Python. Default [Mathish mode](https://answerdotai.github.io/basedpl/numbers.html#mathish-mode) uses relative tolerance `1E¯14` for 64-bit comparisons and defines `0÷0=0` for [Mathish types](https://answerdotai.github.io/basedpl/terms.html#term-mathish-types). See the [language principles](https://answerdotai.github.io/basedpl/principles.html) for the language design, the [glyph reference](https://answerdotai.github.io/basedpl/glyphs.html) for Dyalog differences and [Arrays](https://answerdotai.github.io/basedpl/arrays.html) for the array model.
|
|
92
92
|
|
|
93
93
|
### Numbers
|
|
94
94
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"name": "string.quoted.single.bpl"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
-
"match": "(?:_\\d+|_\\S|_|[^\\s\\p{Cc}0-9
|
|
48
|
+
"match": "(?:_\\d+|_\\S|_|[^\\s\\p{Cc}0-9←⎕•⍺⍵⍶⍹∇⍢⍝⋄\\?¯∞⍬\\+\\-×÷⌈⌊\\|\\*⍟○π√!∧∨⊼⊽\\~=≠<≤>≥⍳↦:⍴≢≡,⍪⊂⊃⊆∊∪∩⍋⍒↑↓⌽⊖⍉⊤⊥⍎⍕⌷⌹\\#↕⍭⨸⌻⍸⍷⊢⊣¿¨ᵇ⍨↣⍤∘⍠⍥↢\\.⊗⌸⍣⇄⊘@∂⍚⌺/⌿\\\\⍀⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ₀₁₂₃₄₅₆₇₈₉₋ₓ₁ₓ₂ₓ₄ₓ₈ₓₕₛₚ\\(\\)\\[\\]\\{\\}'\";\\$_ₑⱼᵣ])+",
|
|
49
49
|
"name": "variable.other.bpl"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"name": "support.function.bpl"
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
|
-
"match": "[¯]?[∞]|[¯]?(\\d+([.]\\d+)?|[.]\\d+)([eEₑ][¯]?\\d+)?([jJⱼ][¯]?(\\d+([.]\\d+)?|[.]\\d+)([eEₑ][¯]?\\d+)
|
|
56
|
+
"match": "(?:[¯]?[∞]|[¯]?(\\d+([.]\\d+)?|[.]\\d+)([eEₑ][¯]?\\d+)?([jJⱼ][¯]?(\\d+([.]\\d+)?|[.]\\d+)([eEₑ][¯]?\\d+)?|[rᵣ][¯]?\\d+)?)(?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ)?|[ₑⱼᵣ]",
|
|
57
57
|
"name": "constant.numeric.bpl"
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
"match": "[⍬]
|
|
60
|
+
"match": "[⍬](?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ)?",
|
|
61
61
|
"name": "constant.numeric.bpl"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
"name": "string.quoted.double.bpl"
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
|
-
"begin": "[\\])](
|
|
72
|
+
"begin": "[\\])](?=(?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ))",
|
|
73
73
|
"beginCaptures": {
|
|
74
74
|
"0": {
|
|
75
75
|
"name": "source.bpl"
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
|
-
"end": "
|
|
78
|
+
"end": "(?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ)|$",
|
|
79
79
|
"contentName": "constant.numeric.bpl",
|
|
80
80
|
"patterns": [],
|
|
81
81
|
"applyEndPatternLast": true,
|
|
@@ -89,6 +89,10 @@
|
|
|
89
89
|
"match": "[\\+\\-×÷⌈⌊\\|\\*⍟○π√!∧∨⊼⊽\\~=≠<≤>≥⍳↦:⍴≢≡,⍪⊂⊃⊆∊∪∩⍋⍒↑↓⌽⊖⍉⊤⊥⍎⍕⌷⌹\\#↕⍭⨸⌻⍸⍷⊢⊣¿]",
|
|
90
90
|
"name": "support.function.bpl"
|
|
91
91
|
},
|
|
92
|
+
{
|
|
93
|
+
"match": "(?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ)",
|
|
94
|
+
"name": "keyword.operator.monadic.bpl"
|
|
95
|
+
},
|
|
92
96
|
{
|
|
93
97
|
"match": "[¨ᵇ⍨⊗⌸⇄∂/⌿\\\\⍀⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ]",
|
|
94
98
|
"name": "keyword.operator.monadic.bpl"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"applyEndPatternLast": true
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
"match": "(?:_\\d+|_\\S|_|[^\\s\\p{Cc}0-9
|
|
22
|
+
"match": "(?:_\\d+|_\\S|_|[^\\s\\p{Cc}0-9←是⎕出入•系⍺甲⍵乙⍶丙⍹丁∇递遞⍢循⍝注⋄句\\?若¯负負∞永⍬空\\+加\\-减減×乘号號÷除⌈上⌊下\\|绝余絕餘\\*幂冪⍟对對○圆圓π周√根!阶拣階揀∧极且極∨析或⊼方否⊽双莫雙\\~非无無=等≠别初別<小≤限退>大≥达进達進⍳位↦至:键卸鍵⍴形≢数异數異≡同深,连連⍪接矩⊂包⊃选合選⊆巢段∊属展屬∪并独併獨∩交重⍋升⍒降↑取↓去拆⌽转轉⊖纵縱⍉翻⊤编編⊥译譯⍎行⍕文⌷索⌹解逆\\#复複↕窗⍭素⨸因⌻零值⍸处间處間⍷寻群尋⊢右⊣左¿掷抽擲¨遍ᵇ按⍨己换換↣先⍤秩∘承⍠轴軸⍥经經↢后後\\.内內⊗表⌸组組⍣次止⇄优優⊘兼@于於∂导梯導⍚择擇⌺邻鄰/总總⌿汇匯\\\\累⍀续續⁰¹²³⁴⁵⁶⁷⁸⁹⁻ᵀᵘₓ₀₁₂₃₄₅₆₇₈₉₋ₓ₁ₓ₂ₓ₄ₓ₈ₓₕₛₚ\\(\\)\\[\\]\\{\\}'\";\\$_ₑⱼᵣ])+",
|
|
23
23
|
"name": "variable.other.bpl"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"name": "support.function.bpl"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
|
-
"match": "[¯负負]?[∞永]|[¯负負]?(\\d+([.内內]\\d+)?|[.内內]\\d+)([eEₑ][¯负負]?\\d+)?([jJⱼ][¯负負]?(\\d+([.内內]\\d+)?|[.内內]\\d+)([eEₑ][¯负負]?\\d+)
|
|
30
|
+
"match": "(?:[¯负負]?[∞永]|[¯负負]?(\\d+([.内內]\\d+)?|[.内內]\\d+)([eEₑ][¯负負]?\\d+)?([jJⱼ][¯负負]?(\\d+([.内內]\\d+)?|[.内內]\\d+)([eEₑ][¯负負]?\\d+)?|[rᵣ][¯负負]?\\d+)?)(?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ)?|[ₑⱼᵣ]",
|
|
31
31
|
"name": "constant.numeric.bpl"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"match": "[⍬空]
|
|
34
|
+
"match": "[⍬空](?:ₓ₁|ₓ₂|ₓ₄|ₓ₈|ₓ|ₕ|ₛ|ₚ)?",
|
|
35
35
|
"name": "constant.numeric.bpl"
|
|
36
36
|
},
|
|
37
37
|
{
|