Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
320 lines
6.7 KiB
Plaintext
320 lines
6.7 KiB
Plaintext
;; lib/prolog/tests/iso_predicates.sx — succ/2, plus/3, between/3, length/2, last/2, nth0/3, nth1/3, max/min arith
|
|
|
|
(define pl-ip-test-count 0)
|
|
(define pl-ip-test-pass 0)
|
|
(define pl-ip-test-fail 0)
|
|
(define pl-ip-test-failures (list))
|
|
|
|
(define
|
|
pl-ip-test!
|
|
(fn
|
|
(name got expected)
|
|
(begin
|
|
(set! pl-ip-test-count (+ pl-ip-test-count 1))
|
|
(if
|
|
(= got expected)
|
|
(set! pl-ip-test-pass (+ pl-ip-test-pass 1))
|
|
(begin
|
|
(set! pl-ip-test-fail (+ pl-ip-test-fail 1))
|
|
(append!
|
|
pl-ip-test-failures
|
|
(str name "\n expected: " expected "\n got: " got)))))))
|
|
|
|
(define
|
|
pl-ip-goal
|
|
(fn
|
|
(src env)
|
|
(pl-instantiate (nth (first (pl-parse (str "g :- " src "."))) 2) env)))
|
|
|
|
(define pl-ip-db (pl-mk-db))
|
|
|
|
;; ── succ/2 ──
|
|
|
|
(define pl-ip-env-s1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "succ(3, X)" pl-ip-env-s1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"succ(3, X) → X=4"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-s1 "X")))
|
|
4)
|
|
|
|
(define pl-ip-env-s2 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "succ(0, X)" pl-ip-env-s2)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"succ(0, X) → X=1"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-s2 "X")))
|
|
1)
|
|
|
|
(define pl-ip-env-s3 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "succ(X, 5)" pl-ip-env-s3)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"succ(X, 5) → X=4"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-s3 "X")))
|
|
4)
|
|
|
|
(pl-ip-test!
|
|
"succ(X, 0) fails"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "succ(X, 0)" {})
|
|
(pl-mk-trail))
|
|
false)
|
|
|
|
;; ── plus/3 ──
|
|
|
|
(define pl-ip-env-p1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "plus(2, 3, X)" pl-ip-env-p1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"plus(2, 3, X) → X=5"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-p1 "X")))
|
|
5)
|
|
|
|
(define pl-ip-env-p2 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "plus(2, X, 7)" pl-ip-env-p2)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"plus(2, X, 7) → X=5"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-p2 "X")))
|
|
5)
|
|
|
|
(define pl-ip-env-p3 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "plus(X, 3, 7)" pl-ip-env-p3)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"plus(X, 3, 7) → X=4"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-p3 "X")))
|
|
4)
|
|
|
|
(pl-ip-test!
|
|
"plus(0, 0, 0) succeeds"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "plus(0, 0, 0)" {})
|
|
(pl-mk-trail))
|
|
true)
|
|
|
|
;; ── between/3 ──
|
|
|
|
(pl-ip-test!
|
|
"between(1, 3, X): 3 solutions"
|
|
(pl-solve-count!
|
|
pl-ip-db
|
|
(pl-ip-goal "between(1, 3, X)" {})
|
|
(pl-mk-trail))
|
|
3)
|
|
|
|
(pl-ip-test!
|
|
"between(1, 3, 2) succeeds"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "between(1, 3, 2)" {})
|
|
(pl-mk-trail))
|
|
true)
|
|
|
|
(pl-ip-test!
|
|
"between(1, 3, 5) fails"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "between(1, 3, 5)" {})
|
|
(pl-mk-trail))
|
|
false)
|
|
|
|
(pl-ip-test!
|
|
"between(5, 3, X): 0 solutions (empty range)"
|
|
(pl-solve-count!
|
|
pl-ip-db
|
|
(pl-ip-goal "between(5, 3, X)" {})
|
|
(pl-mk-trail))
|
|
0)
|
|
|
|
(define pl-ip-env-b1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "between(1, 5, X)" pl-ip-env-b1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"between(1, 5, X): first solution X=1"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-b1 "X")))
|
|
1)
|
|
|
|
(pl-ip-test!
|
|
"between + condition: between(1,5,X), X > 3 → 2 solutions"
|
|
(pl-solve-count!
|
|
pl-ip-db
|
|
(pl-ip-goal "between(1, 5, X), X > 3" {})
|
|
(pl-mk-trail))
|
|
2)
|
|
|
|
;; ── length/2 ──
|
|
|
|
(define pl-ip-env-l1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "length([1,2,3], N)" pl-ip-env-l1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"length([1,2,3], N) → N=3"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-l1 "N")))
|
|
3)
|
|
|
|
(define pl-ip-env-l2 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "length([], N)" pl-ip-env-l2)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"length([], N) → N=0"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-l2 "N")))
|
|
0)
|
|
|
|
(pl-ip-test!
|
|
"length([a,b], 2) check succeeds"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "length([a,b], 2)" {})
|
|
(pl-mk-trail))
|
|
true)
|
|
|
|
(define pl-ip-env-l3 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "length(L, 3)" pl-ip-env-l3)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"length(L, 3): L is a list of length 3"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "length(L, 3), is_list(L)" pl-ip-env-l3)
|
|
(pl-mk-trail))
|
|
true)
|
|
|
|
;; ── last/2 ──
|
|
|
|
(define pl-ip-env-la1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "last([1,2,3], X)" pl-ip-env-la1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"last([1,2,3], X) → X=3"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-la1 "X")))
|
|
3)
|
|
|
|
(define pl-ip-env-la2 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "last([a], X)" pl-ip-env-la2)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"last([a], X) → X=a"
|
|
(pl-atom-name (pl-walk-deep (dict-get pl-ip-env-la2 "X")))
|
|
"a")
|
|
|
|
(pl-ip-test!
|
|
"last([], X) fails"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "last([], X)" {})
|
|
(pl-mk-trail))
|
|
false)
|
|
|
|
;; ── nth0/3 ──
|
|
|
|
(define pl-ip-env-n0 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "nth0(0, [a,b,c], X)" pl-ip-env-n0)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"nth0(0, [a,b,c], X) → X=a"
|
|
(pl-atom-name (pl-walk-deep (dict-get pl-ip-env-n0 "X")))
|
|
"a")
|
|
|
|
(define pl-ip-env-n1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "nth0(2, [a,b,c], X)" pl-ip-env-n1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"nth0(2, [a,b,c], X) → X=c"
|
|
(pl-atom-name (pl-walk-deep (dict-get pl-ip-env-n1 "X")))
|
|
"c")
|
|
|
|
(pl-ip-test!
|
|
"nth0(5, [a,b,c], X) fails"
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "nth0(5, [a,b,c], X)" {})
|
|
(pl-mk-trail))
|
|
false)
|
|
|
|
;; ── nth1/3 ──
|
|
|
|
(define pl-ip-env-n1a {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "nth1(1, [a,b,c], X)" pl-ip-env-n1a)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"nth1(1, [a,b,c], X) → X=a"
|
|
(pl-atom-name (pl-walk-deep (dict-get pl-ip-env-n1a "X")))
|
|
"a")
|
|
|
|
(define pl-ip-env-n1b {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "nth1(3, [a,b,c], X)" pl-ip-env-n1b)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"nth1(3, [a,b,c], X) → X=c"
|
|
(pl-atom-name (pl-walk-deep (dict-get pl-ip-env-n1b "X")))
|
|
"c")
|
|
|
|
;; ── max/min in arithmetic ──
|
|
|
|
(define pl-ip-env-m1 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "X is max(3, 5)" pl-ip-env-m1)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"X is max(3, 5) → X=5"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-m1 "X")))
|
|
5)
|
|
|
|
(define pl-ip-env-m2 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "X is min(3, 5)" pl-ip-env-m2)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"X is min(3, 5) → X=3"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-m2 "X")))
|
|
3)
|
|
|
|
(define pl-ip-env-m3 {})
|
|
(pl-solve-once!
|
|
pl-ip-db
|
|
(pl-ip-goal "X is max(7, 2) + min(1, 4)" pl-ip-env-m3)
|
|
(pl-mk-trail))
|
|
(pl-ip-test!
|
|
"X is max(7,2) + min(1,4) → X=8"
|
|
(pl-num-val (pl-walk-deep (dict-get pl-ip-env-m3 "X")))
|
|
8)
|
|
|
|
(define pl-iso-predicates-tests-run! (fn () {:failed pl-ip-test-fail :passed pl-ip-test-pass :total pl-ip-test-count :failures pl-ip-test-failures})) |