;; lib/kernel/tests/parse.sx — exercises lib/kernel/parser.sx. (define knl-test-pass 0) (define knl-test-fail 0) (define knl-test-fails (list)) (define knl-test (fn (name actual expected) (if (= actual expected) (set! knl-test-pass (+ knl-test-pass 1)) (begin (set! knl-test-fail (+ knl-test-fail 1)) (append! knl-test-fails {:name name :actual actual :expected expected}))))) ;; ── atoms: numbers ──────────────────────────────────────────────── (knl-test "num: integer" (kernel-parse "42") 42) (knl-test "num: zero" (kernel-parse "0") 0) (knl-test "num: negative integer" (kernel-parse "-7") -7) (knl-test "num: positive sign" (kernel-parse "+5") 5) (knl-test "num: float" (kernel-parse "3.14") 3.14) (knl-test "num: negative float" (kernel-parse "-2.5") -2.5) (knl-test "num: leading dot" (kernel-parse ".5") 0.5) (knl-test "num: exponent" (kernel-parse "1e3") 1000) (knl-test "num: exponent with sign" (kernel-parse "2.5e-1") 0.25) (knl-test "num: capital E exponent" (kernel-parse "1E2") 100) ;; ── atoms: booleans ─────────────────────────────────────────────── (knl-test "bool: true" (kernel-parse "#t") true) (knl-test "bool: false" (kernel-parse "#f") false) ;; ── atoms: empty list (Kernel nil) ──────────────────────────────── (knl-test "nil: ()" (kernel-parse "()") (list)) (knl-test "nil: (= () (list))" (= (kernel-parse "()") (list)) true) ;; ── atoms: symbols ──────────────────────────────────────────────── (knl-test "sym: word" (kernel-parse "foo") "foo") (knl-test "sym: hyphenated" (kernel-parse "foo-bar") "foo-bar") (knl-test "sym: dollar-bang" (kernel-parse "$define!") "$define!") (knl-test "sym: question" (kernel-parse "null?") "null?") (knl-test "sym: lt-eq" (kernel-parse "<=") "<=") (knl-test "sym: bare plus" (kernel-parse "+") "+") (knl-test "sym: bare minus" (kernel-parse "-") "-") (knl-test "sym: plus-letter" (kernel-parse "+a") "+a") (knl-test "sym: arrow" (kernel-parse "->") "->") (knl-test "sym: dot-prefixed" (kernel-parse ".foo") ".foo") ;; ── atoms: strings ──────────────────────────────────────────────── (knl-test "str: empty" (kernel-string-value (kernel-parse "\"\"")) "") (knl-test "str: hello" (kernel-string-value (kernel-parse "\"hello\"")) "hello") (knl-test "str: predicate" (kernel-string? (kernel-parse "\"x\"")) true) (knl-test "str: not symbol" (kernel-string? (kernel-parse "x")) false) (knl-test "str: escape newline" (kernel-string-value (kernel-parse "\"a\\nb\"")) "a\nb") (knl-test "str: escape tab" (kernel-string-value (kernel-parse "\"a\\tb\"")) "a\tb") (knl-test "str: escape quote" (kernel-string-value (kernel-parse "\"a\\\"b\"")) "a\"b") (knl-test "str: escape backslash" (kernel-string-value (kernel-parse "\"a\\\\b\"")) "a\\b") ;; ── lists ───────────────────────────────────────────────────────── (knl-test "list: flat" (kernel-parse "(a b c)") (list "a" "b" "c")) (knl-test "list: nested" (kernel-parse "(a (b c) d)") (list "a" (list "b" "c") "d")) (knl-test "list: deeply nested" (kernel-parse "(((x)))") (list (list (list "x")))) (knl-test "list: mixed atoms" (kernel-parse "(1 #t foo)") (list 1 true "foo")) (knl-test "list: empty inside" (kernel-parse "(a () b)") (list "a" (list) "b")) ;; ── whitespace + comments ───────────────────────────────────────── (knl-test "ws: leading" (kernel-parse " 42") 42) (knl-test "ws: trailing" (kernel-parse "42 ") 42) (knl-test "ws: tabs/newlines" (kernel-parse "\n\t 42 \n") 42) (knl-test "comment: line" (kernel-parse "; nope\n42") 42) (knl-test "comment: trailing" (kernel-parse "42 ; tail") 42) (knl-test "comment: inside list" (kernel-parse "(a ; mid\n b)") (list "a" "b")) ;; ── parse-all ───────────────────────────────────────────────────── (knl-test "all: empty input" (kernel-parse-all "") (list)) (knl-test "all: only whitespace" (kernel-parse-all " ") (list)) (knl-test "all: only comment" (kernel-parse-all "; nope") (list)) (knl-test "all: three forms" (kernel-parse-all "1 2 3") (list 1 2 3)) (knl-test "all: mixed" (kernel-parse-all "($if #t 1 2) foo") (list (list "$if" true 1 2) "foo")) ;; ── classic Kernel programs (smoke) ─────────────────────────────── (knl-test "klisp: vau form" (kernel-parse "($vau (x e) e (eval x e))") (list "$vau" (list "x" "e") "e" (list "eval" "x" "e"))) (knl-test "klisp: define lambda" (kernel-parse "($define! sq ($lambda (x) (* x x)))") (list "$define!" "sq" (list "$lambda" (list "x") (list "*" "x" "x")))) ;; ── round-trip identity for primitive symbols ───────────────────── (knl-test "identity: $vau" (kernel-parse "$vau") "$vau") (knl-test "identity: $lambda" (kernel-parse "$lambda") "$lambda") (knl-test "identity: wrap" (kernel-parse "wrap") "wrap") (knl-test "identity: unwrap" (kernel-parse "unwrap") "unwrap") (define knl-tests-run! (fn () {:total (+ knl-test-pass knl-test-fail) :passed knl-test-pass :failed knl-test-fail :fails knl-test-fails}))