;; lib/minikanren/tests/btree-walko.sx — walk a leaves-of-binary-tree relation
;; using matche dispatch on (:leaf v) and (:node left right) patterns.

(define
  btree-walko
  (fn
    (tree v)
    (matche
      tree
      ((:leaf x) (== v x))
      ((:node l r) (conde ((btree-walko l v)) ((btree-walko r v)))))))

;; A small test tree: ((1 2) (3 (4 5))).
(define
  test-btree
  (list
    :node (list :node (list :leaf 1) (list :leaf 2))
    (list
      :node (list :leaf 3)
      (list :node (list :leaf 4) (list :leaf 5)))))

(mk-test
  "btree-walko-enumerates-all-leaves"
  (let
    ((leaves (run* q (btree-walko test-btree q))))
    (and
      (= (len leaves) 5)
      (and
        (some (fn (l) (= l 1)) leaves)
        (and
          (some (fn (l) (= l 2)) leaves)
          (and
            (some (fn (l) (= l 3)) leaves)
            (and
              (some (fn (l) (= l 4)) leaves)
              (some (fn (l) (= l 5)) leaves)))))))
  true)

(mk-test
  "btree-walko-find-3-membership"
  (run 1 q (btree-walko test-btree 3))
  (list (make-symbol "_.0")))

(mk-test
  "btree-walko-find-99-not-present"
  (run* q (btree-walko test-btree 99))
  (list))

(mk-test
  "btree-walko-leaf-only"
  (run* q (btree-walko (list :leaf 42) q))
  (list 42))

(mk-tests-run!)
