Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
Squash merge of 76 commits from loops/minikanren. Adds lib/minikanren/ — a complete miniKanren-on-SX implementation built on top of lib/guest/match.sx, validating the lib-guest unify-and-match kit as intended. Modules (20 .sx files, ~1700 LOC): unify, stream, goals, fresh, conde, condu, conda, run, relations, peano, intarith, project, nafc, matche, fd, queens, defrel, clpfd, tabling Phases 1–5 fully done (core miniKanren API, all classic relations, matche, conda, project, nafc). Phase 6 — native CLP(FD): domain primitives, fd-in / fd-eq / fd-neq / fd-lt / fd-lte / fd-plus / fd-times / fd-distinct / fd-label, with constraint reactivation iterating to fixed point. N-queens via FD: 4-queens 2 solutions, 5-queens 10 solutions (vs naive timeout past N=4). Phase 7 — naive ground-arg tabling: table-1 / table-2 / table-3. Fibonacci canary: tab-fib(25) = 75025 in seconds, naive fib(25) times out at 60s. Ackermann via table-3: A(3,3) = 61. 71 test files, 644+ tests passing across the suite. Producer/consumer SLG (cyclic patho, mutual recursion) deferred — research-grade work. The lib-guest validation experiment is conclusive: lib/minikanren/ unify.sx adds ~50 lines of local logic (custom cfg, deep walk*, fresh counter) over lib/guest/match.sx's ~100-line kit. The kit earns its keep ~3× by line count.
115 lines
2.3 KiB
Plaintext
115 lines
2.3 KiB
Plaintext
;; lib/minikanren/tests/run.sx — Phase 3 tests for run* / run / reify.
|
|
|
|
;; --- canonical TRS one-liners ---
|
|
|
|
(mk-test "run*-eq-one" (run* q (== q 1)) (list 1))
|
|
(mk-test "run*-eq-string" (run* q (== q "hello")) (list "hello"))
|
|
(mk-test "run*-eq-symbol" (run* q (== q (quote sym))) (list (quote sym)))
|
|
(mk-test "run*-fail-empty" (run* q (== 1 2)) (list))
|
|
|
|
;; --- run with a count ---
|
|
|
|
(mk-test
|
|
"run-3-of-many"
|
|
(run
|
|
3
|
|
q
|
|
(conde
|
|
((== q 1))
|
|
((== q 2))
|
|
((== q 3))
|
|
((== q 4))
|
|
((== q 5))))
|
|
(list 1 2 3))
|
|
|
|
(mk-test "run-zero-empty" (run 0 q (== q 1)) (list))
|
|
|
|
(mk-test
|
|
"run-1-takes-one"
|
|
(run 1 q (conde ((== q "a")) ((== q "b"))))
|
|
(list "a"))
|
|
|
|
;; --- reification: unbound vars get _.N left-to-right ---
|
|
|
|
(mk-test
|
|
"reify-single-unbound"
|
|
(run* q (fresh (x) (== q x)))
|
|
(list (make-symbol "_.0")))
|
|
|
|
(mk-test
|
|
"reify-pair-unbound"
|
|
(run* q (fresh (x y) (== q (list x y))))
|
|
(list (list (make-symbol "_.0") (make-symbol "_.1"))))
|
|
|
|
(mk-test
|
|
"reify-mixed-bound-unbound"
|
|
(run* q (fresh (x y) (== q (list 1 x 2 y))))
|
|
(list
|
|
(list 1 (make-symbol "_.0") 2 (make-symbol "_.1"))))
|
|
|
|
(mk-test
|
|
"reify-shared-unbound-same-name"
|
|
(run* q (fresh (x) (== q (list x x))))
|
|
(list (list (make-symbol "_.0") (make-symbol "_.0"))))
|
|
|
|
(mk-test
|
|
"reify-distinct-unbound-distinct-names"
|
|
(run* q (fresh (x y) (== q (list x y x y))))
|
|
(list
|
|
(list
|
|
(make-symbol "_.0")
|
|
(make-symbol "_.1")
|
|
(make-symbol "_.0")
|
|
(make-symbol "_.1"))))
|
|
|
|
;; --- conde + run* ---
|
|
|
|
(mk-test
|
|
"run*-conde-three"
|
|
(run*
|
|
q
|
|
(conde ((== q 1)) ((== q 2)) ((== q 3))))
|
|
(list 1 2 3))
|
|
|
|
(mk-test
|
|
"run*-conde-fresh-mix"
|
|
(run*
|
|
q
|
|
(conde ((fresh (x) (== q (list 1 x)))) ((== q "ground"))))
|
|
(list (list 1 (make-symbol "_.0")) "ground"))
|
|
|
|
;; --- run* + conjunction ---
|
|
|
|
(mk-test
|
|
"run*-conj-binds-q"
|
|
(run* q (fresh (x) (== x 5) (== q (list x x))))
|
|
(list (list 5 5)))
|
|
|
|
;; --- run* + condu ---
|
|
|
|
(mk-test
|
|
"run*-condu-first-wins"
|
|
(run* q (condu ((== q 1)) ((== q 2))))
|
|
(list 1))
|
|
|
|
(mk-test
|
|
"run*-onceo-trim"
|
|
(run* q (onceo (conde ((== q "a")) ((== q "b")))))
|
|
(list "a"))
|
|
|
|
;; --- multi-goal run ---
|
|
|
|
(mk-test
|
|
"run*-three-goals"
|
|
(run*
|
|
q
|
|
(fresh
|
|
(x y z)
|
|
(== x 1)
|
|
(== y 2)
|
|
(== z 3)
|
|
(== q (list x y z))))
|
|
(list (list 1 2 3)))
|
|
|
|
(mk-tests-run!)
|