(ns test.unify-matcher
  (:use clojure.contrib.test-is))

(require 'src.unify-matcher)
(alias 'um 'src.unify-matcher)

(deftest test-var?
  (is (um/var? '?x))
  (is (not (um/var? 'x))))

(deftest test-wild-card?
  (is (um/wild-card? '?*x))
  (is (not (um/wild-card? '?x)))
  (is (not (um/wild-card? 'a)))
  (is (not (um/wild-card? '(?*x)))))

(deftest test-unify
  (is (= (um/unify '(?x ?y c) '(a ?x ?z))
         '{?x a, ?y ?x, ?z c}))
  (is (= (um/unify '(?x ?*xs) '(a b c d))
         '{?x a, ?*xs (b c d)}))
  (is (= (um/unify '[?x ?y c] '(a ?x ?z))
         '{?x a, ?y ?x, ?z c}))
  (is (um/fail? (um/unify '(?x b) '(a ?x))))
  (is (um/fail? (um/unify '(nil) ())))
  )

(deftest test-subst
  (let [b (um/unify '(?x ?y c) '(a ?x ?z))]
    (is (= (um/subst b '?x) 'a))
    (is (= (um/subst b '?y) 'a))
    (is (= (um/subst b '?z) 'c)))
  (let [b (um/unify '(?x ?*xs) '(a b c d))]
    (is (= (um/subst b '?x) 'a))
    (is (= (um/subst b '?*xs) '(b c d))))
  (let [b (um/unify '(?x ?*xs) '(a))]
    (is (= (um/subst b '?x) 'a))
    (is (= (um/subst b '?*xs) ()))
    ))

(deftest test-subst-tree
  (let [b '{?x 0, ?y 1, ?*z [2 3 4]}]
    (is (= (um/subst-tree b '[?x ?y ?*z])
           '[0 1 2 3 4]))
    (is (= (um/subst-tree b '[?*z ?x ?y])
           '[2 3 4 0 1]))
    (is (= (um/subst-tree b '[a b [c ?*z] ?y [?*z]])
           '[a b [c 2 3 4] 1 [2 3 4]]))))

(deftest test-vars-in
  (is (= (um/vars-in '((?x (?y ?z) ?*xs) ?a b ?*c))
         '#{?x ?y ?z ?*xs ?a ?*c})))

(deftest test-if-match
  (let [b (um/unify (macroexpand-1
                      '(um/if-match p s
                         (list ?a ?b) nil))
                    '(clojure.core/let [?gb (src.unify-matcher/unify p s)]
                       (if (src.unify-matcher/fail? ?gb)
                         nil
                         (clojure.core/let
                           [?a (src.unify-matcher/subst ?gb '?a)
                            ?b (src.unify-matcher/subst ?gb '?b)]
                           (list ?a ?b)
                           ))))]
    (let [?gb (um/subst b '?gb)
          ?a (um/subst b '?a)
          ?b (um/subst b '?b)]
      (is (= ?a '?a))
      (is (= ?b '?b))
      (is (and (not (= ?a ?gb))
               (not (= ?b ?gb))
               )))))

(deftest test-if-match-2
  (is (= (um/if-match '(?x ?y) '(a b)
           (list ?x ?y))
         '(a b))))

(run-tests)
