From 04b0e61a33f490a070b4eaf2bba1f3064f6a8209 Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 7 May 2026 19:47:37 +0000 Subject: [PATCH] =?UTF-8?q?plans:=20Phase=209=20=E2=80=94=20make=20.apl=20?= =?UTF-8?q?source=20files=20run=20as-written?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Goal: existing lib/apl/tests/programs/*.apl execute through apl-run unchanged. Sub-tasks: compress-as-fn (mask/arr), inline assignment, ? random, apl-run-file, end-to-end .apl tests, glyph audit. --- plans/apl-on-sx.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/plans/apl-on-sx.md b/plans/apl-on-sx.md index d4d689de..25dbc38d 100644 --- a/plans/apl-on-sx.md +++ b/plans/apl-on-sx.md @@ -177,6 +177,42 @@ programs run from source, and starts pushing on performance. 300 s timeout). Target: profile the inner loop, eliminate quadratic list-append, restore the `queens(8)` test. +### Phase 9 — make `.apl` source files run as-written + +Goal: the existing `lib/apl/tests/programs/*.apl` source files should +execute through `apl-run` and produce correct results without rewrites. +Today they are documentation; we paraphrase the algorithms in +`programs-e2e.sx`. Phase 9 closes that gap. + +- [ ] **Compress as a dyadic function** — `mask / arr` between two values + is the classic compress (select where mask≠0). Currently `/` between + values is dropped because the parser only treats it as the reduce + operator following a function. Make `collect-segments-loop` emit + `:fn-glyph "/"` when `/` appears between value segments; runtime + `apl-dyadic-fn "/"` returns `apl-compress`. Same for `⌿` + (first-axis compress). +- [ ] **Inline assignment** — `⍵ ← ⍳⍵` mid-expression. Parser currently + only handles `:assign` at the start of a statement. Extend + `collect-segments-loop` (or `parse-apl-expr`) to recognise + `` as a value-producing sub-expression, emitting a + `(:assign-expr name expr)` AST whose value is the assigned RHS. + Required by the primes idiom `(2=+⌿0=⍵∘.|⍵)/⍵←⍳⍵`. +- [ ] **`?` (random / roll)** — monadic `?N` returns a random integer + in 1..N. Used by quicksort.apl for pivot selection. Add `apl-roll` + (deterministic seed for tests) + glyph wiring. +- [ ] **`apl-run-file path → array`** — read the file from disk, strip + the `⍝` comments (already handled by tokenizer), and run. Needs an + IO primitive on the SX side. Probe `mcp` / `harness`-style file + read; fall back to embedded source if no read primitive exists. +- [ ] **End-to-end .apl tests** — once the above land, add tests that + run `lib/apl/tests/programs/*.apl` *as written* and assert results. + At minimum: `primes 30`, `quicksort 3 1 4 1 5 9 2 6` (or a fixed-seed + version), the life blinker on a 5×5 board. +- [ ] **Audit silently-skipped glyphs** — sweep `apl-glyph-set` and + `apl-parse-fn-glyphs` against the runtime's `apl-monadic-fn` and + `apl-dyadic-fn` cond chains to find any that the runtime supports + but the parser doesn't see. + ## SX primitive baseline Use vectors for arrays; numeric tower + rationals for numbers; ADTs for tagged data; @@ -191,6 +227,7 @@ data; format for string templating. _Newest first._ +- 2026-05-07: Phase 9 added — make .apl source files run as-written (compress as dyadic /, inline assignment, ? random, apl-run-file, glyph audit, source-as-tests) - 2026-05-07: Phase 8 step 6 — perf: swapped (append acc xs) → (append xs acc) in apl-permutations to make permutation generation linear instead of quadratic; q(7) 32s→12s; q(8)=92 test restored within 300s timeout; **Phase 8 complete, all unchecked items ticked**; 497/497 - 2026-05-07: Phase 8 step 5 — train/fork notation. Parser :lparen detects all-fn inner segments → emits :train AST; resolver covers 2-atop & 3-fork for both monadic and dyadic. `(+/÷≢) 1..5 → 3` (mean), `(- ⌊) 5 → -5` (atop), `2(+×-)5 → -21` (dyadic fork), `(⌈/-⌊/) → 8` (range); +6 tests; 496/496 - 2026-05-07: Phase 8 step 4 — programs-e2e.sx runs classic-algorithm shapes through full pipeline (factorial via ∇, triangulars, sum-of-squares, divisor-counts, prime-mask, named-fn composition, dyadic max-of-two, Newton step); also added ⌿ + ⍀ to glyph sets (were silently skipped); +15 tests; 490/490