;; lib/guest/tests/ast.sx — exercises every constructor / predicate / ;; accessor in lib/guest/ast.sx so future ports have a stable contract ;; to point at. (define gast-test-pass 0) (define gast-test-fail 0) (define gast-test-fails (list)) (define gast-test (fn (name actual expected) (if (= actual expected) (set! gast-test-pass (+ gast-test-pass 1)) (begin (set! gast-test-fail (+ gast-test-fail 1)) (append! gast-test-fails {:name name :expected expected :actual actual}))))) ;; Constructors round-trip. (gast-test "literal-int" (ast-literal-value (ast-literal 42)) 42) (gast-test "literal-str" (ast-literal-value (ast-literal "hi")) "hi") (gast-test "literal-bool" (ast-literal-value (ast-literal true)) true) (gast-test "var-name" (ast-var-name (ast-var "x")) "x") (gast-test "app-fn" (ast-app-fn (ast-app (ast-var "f") (list (ast-literal 1)))) (ast-var "f")) (gast-test "app-args-len" (len (ast-app-args (ast-app (ast-var "f") (list (ast-literal 1))))) 1) (gast-test "lambda-params" (ast-lambda-params (ast-lambda (list "x" "y") (ast-var "x"))) (list "x" "y")) (gast-test "lambda-body" (ast-lambda-body (ast-lambda (list "x") (ast-var "x"))) (ast-var "x")) (gast-test "let-bindings" (len (ast-let-bindings (ast-let (list {:name "x" :value (ast-literal 1)}) (ast-var "x")))) 1) (gast-test "letrec-body" (ast-letrec-body (ast-letrec (list) (ast-literal 0))) (ast-literal 0)) (gast-test "if-test" (ast-if-test (ast-if (ast-literal true) (ast-literal 1) (ast-literal 0))) (ast-literal true)) (gast-test "if-then" (ast-if-then (ast-if (ast-literal true) (ast-literal 1) (ast-literal 0))) (ast-literal 1)) (gast-test "if-else" (ast-if-else (ast-if (ast-literal true) (ast-literal 1) (ast-literal 0))) (ast-literal 0)) (gast-test "match-pattern" (ast-match-clause-pattern (ast-match-clause "P" (ast-literal 1))) "P") (gast-test "match-body" (ast-match-clause-body (ast-match-clause "P" (ast-literal 1))) (ast-literal 1)) (gast-test "module-name" (ast-module-name (ast-module "m" (list))) "m") (gast-test "import-name" (ast-import-name (ast-import "lib/foo")) "lib/foo") ;; Predicates fire only on matching kinds. (gast-test "is-literal" (ast-literal? (ast-literal 1)) true) (gast-test "not-literal" (ast-literal? (ast-var "x")) false) (gast-test "is-var" (ast-var? (ast-var "x")) true) (gast-test "is-app" (ast-app? (ast-app (ast-var "f") (list))) true) (gast-test "is-lambda" (ast-lambda? (ast-lambda (list) (ast-literal 0))) true) (gast-test "is-let" (ast-let? (ast-let (list) (ast-literal 0))) true) (gast-test "is-letrec" (ast-letrec? (ast-letrec (list) (ast-literal 0))) true) (gast-test "is-if" (ast-if? (ast-if (ast-literal true) (ast-literal 1) (ast-literal 0))) true) (gast-test "is-match" (ast-match-clause? (ast-match-clause "P" (ast-literal 1))) true) (gast-test "is-module" (ast-module? (ast-module "m" (list))) true) (gast-test "is-import" (ast-import? (ast-import "x")) true) ;; ast? recognises any canonical node. (gast-test "ast?-literal" (ast? (ast-literal 0)) true) (gast-test "ast?-foreign" (ast? (list "lua-num" 0)) false) (gast-test "ast?-non-list" (ast? 42) false) ;; ast-kind dispatch. (gast-test "kind-literal" (ast-kind (ast-literal 0)) :literal) (gast-test "kind-import" (ast-kind (ast-import "x")) :import) (define gast-tests-run! (fn () {:passed gast-test-pass :failed gast-test-fail :total (+ gast-test-pass gast-test-fail)}))