;; lib/guest/tests/match.sx — exercises lib/guest/match.sx. (define gmatch-test-pass 0) (define gmatch-test-fail 0) (define gmatch-test-fails (list)) (define gmatch-test (fn (name actual expected) (if (= actual expected) (set! gmatch-test-pass (+ gmatch-test-pass 1)) (begin (set! gmatch-test-fail (+ gmatch-test-fail 1)) (append! gmatch-test-fails {:name name :expected expected :actual actual}))))) ;; ── walk / extend / occurs ──────────────────────────────────────── (gmatch-test "walk-direct" (walk (mk-var "x") (extend "x" 5 (empty-subst))) 5) (gmatch-test "walk-chain" (walk (mk-var "a") (extend "a" (mk-var "b") (extend "b" 7 (empty-subst)))) 7) (gmatch-test "walk-no-binding" (let ((v (mk-var "u"))) (= (walk v (empty-subst)) v)) true) (gmatch-test "walk*-recursive" (walk* (mk-ctor "Just" (list (mk-var "x"))) (extend "x" 9 (empty-subst))) (mk-ctor "Just" (list 9))) (gmatch-test "occurs-direct" (occurs? "x" (mk-var "x") (empty-subst)) true) (gmatch-test "occurs-nested" (occurs? "x" (mk-ctor "f" (list (mk-var "x"))) (empty-subst)) true) (gmatch-test "occurs-not" (occurs? "x" (mk-var "y") (empty-subst)) false) ;; ── unify (symmetric) ───────────────────────────────────────────── (gmatch-test "unify-equal-literals" (len (unify 5 5 (empty-subst))) 0) (gmatch-test "unify-different-literals" (unify 5 6 (empty-subst)) nil) (gmatch-test "unify-var-literal" (get (unify (mk-var "x") 5 (empty-subst)) "x") 5) (gmatch-test "unify-literal-var" (get (unify 5 (mk-var "x") (empty-subst)) "x") 5) (gmatch-test "unify-same-var" (len (unify (mk-var "x") (mk-var "x") (empty-subst))) 0) (gmatch-test "unify-two-vars" (let ((s (unify (mk-var "x") (mk-var "y") (empty-subst)))) (or (= (get s "x") (mk-var "y")) (= (get s "y") (mk-var "x")))) true) (gmatch-test "unify-ctor-equal" (len (unify (mk-ctor "f" (list 1 2)) (mk-ctor "f" (list 1 2)) (empty-subst))) 0) (gmatch-test "unify-ctor-with-var" (get (unify (mk-ctor "Just" (list (mk-var "x"))) (mk-ctor "Just" (list 7)) (empty-subst)) "x") 7) (gmatch-test "unify-ctor-head-mismatch" (unify (mk-ctor "Just" (list 1)) (mk-ctor "Nothing" (list)) (empty-subst)) nil) (gmatch-test "unify-ctor-arity-mismatch" (unify (mk-ctor "f" (list 1 2)) (mk-ctor "f" (list 1)) (empty-subst)) nil) (gmatch-test "unify-occurs-check" (unify (mk-var "x") (mk-ctor "f" (list (mk-var "x"))) (empty-subst)) nil) (gmatch-test "unify-transitive-vars" (let ((s (unify (mk-var "x") (mk-var "y") (empty-subst)))) (let ((s2 (unify (mk-var "y") 42 s))) (walk (mk-var "x") s2))) 42) ;; ── match-pat (asymmetric) ──────────────────────────────────────── (gmatch-test "match-var-binds" (get (match-pat (mk-var "x") 99 (empty-subst)) "x") 99) (gmatch-test "match-literal-equal" (len (match-pat 5 5 (empty-subst))) 0) (gmatch-test "match-literal-mismatch" (match-pat 5 6 (empty-subst)) nil) (gmatch-test "match-ctor-binds" (get (match-pat (mk-ctor "Just" (list (mk-var "y"))) (mk-ctor "Just" (list 11)) (empty-subst)) "y") 11) (gmatch-test "match-ctor-head-mismatch" (match-pat (mk-ctor "Just" (list (mk-var "y"))) (mk-ctor "Nothing" (list)) (empty-subst)) nil) (gmatch-test "match-ctor-arity-mismatch" (match-pat (mk-ctor "f" (list (mk-var "x") (mk-var "y"))) (mk-ctor "f" (list 1)) (empty-subst)) nil) (define gmatch-tests-run! (fn () {:passed gmatch-test-pass :failed gmatch-test-fail :total (+ gmatch-test-pass gmatch-test-fail)}))