;; String/regex primitive tests (defsuite "string-char-at" (deftest "char-at first" (assert= "h" (char-at "hello" 0))) (deftest "char-at middle" (assert= "l" (char-at "hello" 2))) (deftest "char-at last" (assert= "o" (char-at "hello" 4))) (deftest "char-at out of bounds" (assert= nil (char-at "hello" 10))) (deftest "char-at negative" (assert= nil (char-at "hello" -1)))) (defsuite "string-char-code" (deftest "char-code a" (assert= 97 (char-code "a"))) (deftest "char-code A" (assert= 65 (char-code "A"))) (deftest "char-code 0" (assert= 48 (char-code "0"))) (deftest "char-code space" (assert= 32 (char-code " "))) (deftest "char-code roundtrip" (assert= "a" (char-from-code (char-code "a")))) (deftest "char-from-code roundtrip" (assert= 65 (char-code (char-from-code 65))))) (defsuite "string-parse-number" (deftest "parse-number integer" (assert= 42 (parse-number "42"))) (deftest "parse-number float" (assert= 3.14 (parse-number "3.14"))) (deftest "parse-number negative" (assert= -7 (parse-number "-7"))) (deftest "parse-number negative float" (assert= -2.5 (parse-number "-2.5"))) (deftest "parse-number zero" (assert= 0 (parse-number "0"))) (deftest "parse-number invalid returns nil" (assert= nil (parse-number "abc"))) (deftest "parse-number empty returns nil" (assert= nil (parse-number "")))) (defsuite "regex-match" (deftest "regex-match simple" (let ((r (regex-match "h.llo" "hello world"))) (assert (list? r)) (assert= "hello" (first r)))) (deftest "regex-match no match" (assert= nil (regex-match "xyz" "hello"))) (deftest "regex-match with group" (let ((r (regex-match "(h)ello" "hello"))) (assert (list? r)) (assert= "hello" (first r)) (assert= "h" (nth r 1)))) (deftest "regex-match digits" (let ((r (regex-match "[0-9]+" "abc123def"))) (assert= "123" (first r)))) (deftest "regex-match anchored" (assert= nil (regex-match "^world" "hello world"))) (deftest "regex-match start" (let ((r (regex-match "^hello" "hello world"))) (assert= "hello" (first r))))) (defsuite "regex-match?" (deftest "regex-match? true" (assert (regex-match? "h.llo" "hello"))) (deftest "regex-match? false" (assert (not (regex-match? "xyz" "hello")))) (deftest "regex-match? digit pattern" (assert (regex-match? "[0-9]" "abc1"))) (deftest "regex-match? empty pattern" (assert (regex-match? "" "anything")))) (defsuite "regex-find-all" (deftest "find-all digits" (let ((result (regex-find-all "[0-9]" "a1b2c3"))) (assert= 3 (len result)) (assert= "1" (first result)) (assert= "3" (nth result 2)))) (deftest "find-all words" (let ((result (regex-find-all "[a-z]+" "hello 123 world"))) (assert= 2 (len result)) (assert= "hello" (first result)) (assert= "world" (nth result 1)))) (deftest "find-all no matches" (assert= (list) (regex-find-all "[0-9]" "abc"))) (deftest "find-all multi-char" (let ((result (regex-find-all "ab" "xababx"))) (assert= 2 (len result)) (assert= "ab" (first result)) (assert= "ab" (nth result 1))))) (defsuite "regex-replace" (deftest "replace all digits" (assert= "a_b_c_" (regex-replace "[0-9]" "_" "a1b2c3"))) (deftest "replace word" (assert= "hi hi" (regex-replace "hello" "hi" "hello hello"))) (deftest "replace no match" (assert= "hello" (regex-replace "xyz" "!" "hello"))) (deftest "replace empty pattern" (assert= "hello" (regex-replace "^$" "!" "hello")))) (defsuite "regex-replace-first" (deftest "replace-first digit" (assert= "a_b2c3" (regex-replace-first "[0-9]" "_" "a1b2c3"))) (deftest "replace-first no match" (assert= "hello" (regex-replace-first "xyz" "!" "hello")))) (defsuite "regex-split" (deftest "split on whitespace" (assert= (list "hello" "world") (regex-split "[ \t]+" "hello world"))) (deftest "split on comma-space" (assert= (list "a" "b" "c") (regex-split ", *" "a, b,c"))) (deftest "split no match" (assert= (list "hello") (regex-split ";" "hello"))) (deftest "split digits" (assert= (list "a" "b" "c") (regex-split "[0-9]+" "a1b23c")))) (defsuite "string-split-multichar" (deftest "split on multi-char separator" (assert= (list "a" "b" "c") (split "a::b::c" "::"))) (deftest "split on arrow" (assert= (list "a" "b") (split "a->b" "->"))))