Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s
Three fixes for Iverson's dfn
{1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p}:
1. parser: standalone op-glyph branch (/ ⌿ \ ⍀) now consumes a
following ⍨ or ¨ and emits :derived-fn — `⍵⌿⍨⍵<p` parses
as compress-commute (was previously dropping ⍨)
2. tokenizer: `name←...` (no spaces) now tokenizes as separate
:name + :assign instead of eating ← into the name. ⎕← still
stays one token for the output op
3. inline p←⍵⌷⍨?≢⍵ mid-dfn now works via existing :assign-expr
Full suite 585/585. Phase 10 complete (all 7 items ticked).
Remaining gaps for a future phase: heterogeneous-strand inner
product is the only unfinished part — life works after dropping ⊃,
quicksort works directly.
190 lines
5.9 KiB
Plaintext
190 lines
5.9 KiB
Plaintext
; End-to-end tests of the classic-program archetypes — running APL
|
||
; source through the full pipeline (tokenize → parse → eval-ast → runtime).
|
||
;
|
||
; These mirror the algorithms documented in lib/apl/tests/programs/*.apl
|
||
; but use forms our pipeline supports today (named functions instead of
|
||
; the inline ⍵← rebinding idiom; multi-stmt over single one-liners).
|
||
|
||
(define mkrv (fn (arr) (get arr :ravel)))
|
||
(define mksh (fn (arr) (get arr :shape)))
|
||
|
||
; ---------- factorial via ∇ recursion (cf. n-queens style) ----------
|
||
|
||
(apl-test
|
||
"e2e: factorial 5! = 120"
|
||
(mkrv (apl-run "fact ← {0=⍵:1 ⋄ ⍵×∇⍵-1} ⋄ fact 5"))
|
||
(list 120))
|
||
|
||
(apl-test
|
||
"e2e: factorial 7! = 5040"
|
||
(mkrv (apl-run "fact ← {0=⍵:1 ⋄ ⍵×∇⍵-1} ⋄ fact 7"))
|
||
(list 5040))
|
||
|
||
(apl-test
|
||
"e2e: factorial via ×/⍳N (no recursion)"
|
||
(mkrv (apl-run "fact ← {×/⍳⍵} ⋄ fact 6"))
|
||
(list 720))
|
||
|
||
; ---------- sum / triangular numbers (sum-1..N) ----------
|
||
|
||
(apl-test
|
||
"e2e: triangular(10) = 55"
|
||
(mkrv (apl-run "tri ← {+/⍳⍵} ⋄ tri 10"))
|
||
(list 55))
|
||
|
||
(apl-test
|
||
"e2e: triangular(100) = 5050"
|
||
(mkrv (apl-run "tri ← {+/⍳⍵} ⋄ tri 100"))
|
||
(list 5050))
|
||
|
||
; ---------- sum of squares ----------
|
||
|
||
(apl-test
|
||
"e2e: sum-of-squares 1..5 = 55"
|
||
(mkrv (apl-run "ss ← {+/⍵×⍵} ⋄ ss ⍳5"))
|
||
(list 55))
|
||
|
||
(apl-test
|
||
"e2e: sum-of-squares 1..10 = 385"
|
||
(mkrv (apl-run "ss ← {+/⍵×⍵} ⋄ ss ⍳10"))
|
||
(list 385))
|
||
|
||
; ---------- divisor-counting (prime-sieve building blocks) ----------
|
||
|
||
(apl-test
|
||
"e2e: divisor counts 1..5 via outer mod"
|
||
(mkrv (apl-run "P ← ⍳ 5 ⋄ +⌿ 0 = P ∘.| P"))
|
||
(list 1 2 2 3 2))
|
||
|
||
(apl-test
|
||
"e2e: divisor counts 1..10"
|
||
(mkrv (apl-run "P ← ⍳ 10 ⋄ +⌿ 0 = P ∘.| P"))
|
||
(list 1 2 2 3 2 4 2 4 3 4))
|
||
|
||
(apl-test
|
||
"e2e: prime-mask 1..10 (count==2)"
|
||
(mkrv (apl-run "P ← ⍳ 10 ⋄ 2 = +⌿ 0 = P ∘.| P"))
|
||
(list 0 1 1 0 1 0 1 0 0 0))
|
||
|
||
; ---------- monadic primitives chained ----------
|
||
|
||
(apl-test
|
||
"e2e: sum of |abs| = 15"
|
||
(mkrv (apl-run "+/|¯1 ¯2 ¯3 ¯4 ¯5"))
|
||
(list 15))
|
||
|
||
(apl-test
|
||
"e2e: max of squares 1..6"
|
||
(mkrv (apl-run "⌈/(⍳6)×⍳6"))
|
||
(list 36))
|
||
|
||
; ---------- nested named functions ----------
|
||
|
||
(apl-test
|
||
"e2e: compose dbl and sq via two named fns"
|
||
(mkrv (apl-run "dbl ← {⍵+⍵} ⋄ sq ← {⍵×⍵} ⋄ sq dbl 3"))
|
||
(list 36))
|
||
|
||
(apl-test
|
||
"e2e: max-of-two as named dyadic fn"
|
||
(mkrv (apl-run "mx ← {⍺⌈⍵} ⋄ 5 mx 3"))
|
||
(list 5))
|
||
|
||
(apl-test
|
||
"e2e: sqrt-via-newton 1 step from 1 → 2.5"
|
||
(mkrv (apl-run "step ← {(⍵+⍺÷⍵)÷2} ⋄ 4 step 1"))
|
||
(list 2.5))
|
||
|
||
(begin
|
||
(apl-test
|
||
"life.apl: blinker 5×5 → vertical blinker"
|
||
(mkrv
|
||
(apl-run
|
||
"life ← {1 ⍵ ∨.∧ 3 4 = +/ +/ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵} ⋄ life 5 5 ⍴ 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0"))
|
||
(list 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0))
|
||
(apl-test
|
||
"life.apl: blinker oscillates (period 2)"
|
||
(mkrv
|
||
(apl-run
|
||
"life ← {1 ⍵ ∨.∧ 3 4 = +/ +/ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵} ⋄ life life 5 5 ⍴ 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0"))
|
||
(list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0))
|
||
(apl-test
|
||
"life.apl: 2×2 block stable"
|
||
(mkrv
|
||
(apl-run
|
||
"life ← {1 ⍵ ∨.∧ 3 4 = +/ +/ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵} ⋄ life 4 4 ⍴ 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0"))
|
||
(list 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0))
|
||
(apl-test
|
||
"life.apl: empty grid stays empty"
|
||
(mkrv
|
||
(apl-run
|
||
"life ← {1 ⍵ ∨.∧ 3 4 = +/ +/ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵} ⋄ life 5 5 ⍴ 0"))
|
||
(list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
|
||
(apl-test
|
||
"life.apl: source-file as-written runs"
|
||
(let
|
||
((dfn (apl-run-file "lib/apl/tests/programs/life.apl"))
|
||
(board
|
||
(apl-run "5 5 ⍴ 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0")))
|
||
(get (apl-call-dfn-m dfn board) :ravel))
|
||
(list 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0)))
|
||
|
||
(begin
|
||
(apl-test
|
||
"quicksort.apl: 11-element with duplicates"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(mkrv
|
||
(apl-run
|
||
"quicksort ← {1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p} ⋄ quicksort 3 1 4 1 5 9 2 6 5 3 5")))
|
||
(list 1 1 2 3 3 4 5 5 5 6 9))
|
||
(apl-test
|
||
"quicksort.apl: already sorted"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(mkrv
|
||
(apl-run
|
||
"quicksort ← {1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p} ⋄ quicksort 1 2 3 4 5")))
|
||
(list 1 2 3 4 5))
|
||
(apl-test
|
||
"quicksort.apl: reverse sorted"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(mkrv
|
||
(apl-run
|
||
"quicksort ← {1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p} ⋄ quicksort 5 4 3 2 1")))
|
||
(list 1 2 3 4 5))
|
||
(apl-test
|
||
"quicksort.apl: all equal"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(mkrv
|
||
(apl-run
|
||
"quicksort ← {1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p} ⋄ quicksort 7 7 7 7")))
|
||
(list 7 7 7 7))
|
||
(apl-test
|
||
"quicksort.apl: single element"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(mkrv
|
||
(apl-run
|
||
"quicksort ← {1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p} ⋄ quicksort ,42")))
|
||
(list 42))
|
||
(apl-test
|
||
"quicksort.apl: matches grade-up"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(mkrv
|
||
(apl-run
|
||
"V ← 8 3 1 9 2 7 5 6 4 ⋄ quicksort ← {1≥≢⍵:⍵ ⋄ p←⍵⌷⍨?≢⍵ ⋄ (∇⍵⌿⍨⍵<p),(p=⍵)/⍵,∇⍵⌿⍨⍵>p} ⋄ quicksort V")))
|
||
(list 1 2 3 4 5 6 7 8 9))
|
||
(apl-test
|
||
"quicksort.apl: source-file as-written runs"
|
||
(begin
|
||
(apl-rng-seed! 42)
|
||
(let
|
||
((dfn (apl-run-file "lib/apl/tests/programs/quicksort.apl"))
|
||
(vec (apl-run "5 2 8 1 9 3 7 4 6")))
|
||
(get (apl-call-dfn-m dfn vec) :ravel)))
|
||
(list 1 2 3 4 5 6 7 8 9)))
|