;; lib/prolog/tests/programs/reverse.sx — naive reverse/2 via append/3. ;; ;; Mirrors reverse.pl (embedded as a string here). (define pl-rv-test-count 0) (define pl-rv-test-pass 0) (define pl-rv-test-fail 0) (define pl-rv-test-failures (list)) (define pl-rv-test! (fn (name got expected) (begin (set! pl-rv-test-count (+ pl-rv-test-count 1)) (if (= got expected) (set! pl-rv-test-pass (+ pl-rv-test-pass 1)) (begin (set! pl-rv-test-fail (+ pl-rv-test-fail 1)) (append! pl-rv-test-failures (str name "\n expected: " expected "\n got: " got))))))) (define pl-rv-term-to-sx (fn (t) (cond ((pl-num? t) (pl-num-val t)) ((pl-atom? t) (pl-atom-name t)) (true (list :complex))))) (define pl-rv-list-walked (fn (w) (cond ((and (pl-atom? w) (= (pl-atom-name w) "[]")) (list)) ((and (pl-compound? w) (= (pl-fun w) ".") (= (len (pl-args w)) 2)) (cons (pl-rv-term-to-sx (first (pl-args w))) (pl-rv-list-walked (nth (pl-args w) 1)))) (true (list :not-list))))) (define pl-rv-list-to-sx (fn (t) (pl-rv-list-walked (pl-walk-deep t)))) (define pl-rv-goal (fn (src env) (pl-instantiate (nth (first (pl-parse (str "g :- " src "."))) 2) env))) (define pl-rv-prog-src "reverse([], []). reverse([H|T], R) :- reverse(T, RT), append(RT, [H], R). append([], L, L). append([H|T], L, [H|R]) :- append(T, L, R).") (define pl-rv-db (pl-mk-db)) (pl-db-load! pl-rv-db (pl-parse pl-rv-prog-src)) (define pl-rv-env-1 {}) (define pl-rv-goal-1 (pl-rv-goal "reverse([], X)" pl-rv-env-1)) (pl-solve-once! pl-rv-db pl-rv-goal-1 (pl-mk-trail)) (pl-rv-test! "reverse([], X) → X = []" (pl-rv-list-to-sx (dict-get pl-rv-env-1 "X")) (list)) (define pl-rv-env-2 {}) (define pl-rv-goal-2 (pl-rv-goal "reverse([1], X)" pl-rv-env-2)) (pl-solve-once! pl-rv-db pl-rv-goal-2 (pl-mk-trail)) (pl-rv-test! "reverse([1], X) → X = [1]" (pl-rv-list-to-sx (dict-get pl-rv-env-2 "X")) (list 1)) (define pl-rv-env-3 {}) (define pl-rv-goal-3 (pl-rv-goal "reverse([1, 2, 3], X)" pl-rv-env-3)) (pl-solve-once! pl-rv-db pl-rv-goal-3 (pl-mk-trail)) (pl-rv-test! "reverse([1, 2, 3], X) → X = [3, 2, 1]" (pl-rv-list-to-sx (dict-get pl-rv-env-3 "X")) (list 3 2 1)) (define pl-rv-env-4 {}) (define pl-rv-goal-4 (pl-rv-goal "reverse([a, b, c, d], X)" pl-rv-env-4)) (pl-solve-once! pl-rv-db pl-rv-goal-4 (pl-mk-trail)) (pl-rv-test! "reverse([a, b, c, d], X) → X = [d, c, b, a]" (pl-rv-list-to-sx (dict-get pl-rv-env-4 "X")) (list "d" "c" "b" "a")) (pl-rv-test! "reverse([1, 2, 3], [3, 2, 1]) succeeds" (pl-solve-once! pl-rv-db (pl-rv-goal "reverse([1, 2, 3], [3, 2, 1])" {}) (pl-mk-trail)) true) (pl-rv-test! "reverse([1, 2], [1, 2]) fails" (pl-solve-once! pl-rv-db (pl-rv-goal "reverse([1, 2], [1, 2])" {}) (pl-mk-trail)) false) (define pl-reverse-tests-run! (fn () {:failed pl-rv-test-fail :passed pl-rv-test-pass :total pl-rv-test-count :failures pl-rv-test-failures}))