HS E37: tokenizer-as-API 17/17 (+fixes)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 16s

- runtime.sx: fix extra ) in hs-tokens-of (parse error); add hs-eof-sentinel,
  hs-raw->api-token, hs-normalize-raw-tokens, hs-tokens-of, stream helpers,
  hs-token-type/value/op?; add \$ escape to hs-template
- tokenizer.sx: fix read-number double-dot bug (1.1.1 → 3 tokens); fix t-emit!
  eof call (3→2 args); add bare $ case to scan-template!
- compiler.sx: add \$ escape to tpl-collect template interpolation
- generate-sx-tests.py: preserve \$ in process_hs_val; add generate_tokenizer_test
- regen spec/tests/test-hyperscript-behavioral.sx: 17 tokenizer tests generated
- plans/hs-conformance-to-100.md: row 37 marked done +17

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 09:54:59 +00:00
parent 3003c8a069
commit 880503e2b6
9 changed files with 974 additions and 77 deletions

View File

@@ -2479,41 +2479,287 @@
;; ── core/tokenizer (17 tests) ──
(defsuite "hs-upstream-core/tokenizer"
(deftest "handles $ in template properly"
(error "SKIP (untranslated): handles $ in template properly"))
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"" :template) 0)) "\"")
)
(deftest "handles all special escapes properly"
(error "SKIP (untranslated): handles all special escapes properly"))
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\b\""))) (char-from-code 8))
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\f\""))) (char-from-code 12))
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\n\""))) "\n")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\r\""))) "\r")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\t\""))) "\t")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\v\""))) (char-from-code 11))
)
(deftest "handles basic token types"
(error "SKIP (untranslated): handles basic token types"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "foo"))) "IDENTIFIER")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1"))) "NUMBER")
(let ((s (hs-tokens-of "1.1")))
(let ((tok (hs-stream-consume s)))
(assert= (hs-token-type tok) "NUMBER")
(assert= (hs-stream-has-more s) false)))
(let ((s (hs-tokens-of "1e6")))
(let ((tok (hs-stream-consume s)))
(assert= (hs-token-type tok) "NUMBER")
(assert= (hs-stream-has-more s) false)))
(let ((s (hs-tokens-of "1e-6")))
(let ((tok (hs-stream-consume s)))
(assert= (hs-token-type tok) "NUMBER")
(assert= (hs-stream-has-more s) false)))
(let ((s (hs-tokens-of "1.1e6")))
(let ((tok (hs-stream-consume s)))
(assert= (hs-token-type tok) "NUMBER")
(assert= (hs-stream-has-more s) false)))
(let ((s (hs-tokens-of "1.1e-6")))
(let ((tok (hs-stream-consume s)))
(assert= (hs-token-type tok) "NUMBER")
(assert= (hs-stream-has-more s) false)))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of ".a"))) "CLASS_REF")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "#a"))) "ID_REF")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "\"asdf\""))) "STRING")
)
(deftest "handles class identifiers properly"
(error "SKIP (untranslated): handles class identifiers properly"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of ".a"))) "CLASS_REF")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ".a"))) ".a")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of " .a"))) "CLASS_REF")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of " .a"))) ".a")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "a.a"))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "a.a"))) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "(a).a") "list") 4)) "IDENTIFIER")
(assert= (hs-token-value (nth (get (hs-tokens-of "(a).a") "list") 4)) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "{a}.a") "list") 4)) "IDENTIFIER")
(assert= (hs-token-value (nth (get (hs-tokens-of "{a}.a") "list") 4)) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "[a].a") "list") 4)) "IDENTIFIER")
(assert= (hs-token-value (nth (get (hs-tokens-of "[a].a") "list") 4)) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "(a(.a") "list") 3)) "CLASS_REF")
(assert= (hs-token-value (nth (get (hs-tokens-of "(a(.a") "list") 3)) ".a")
(assert= (hs-token-type (nth (get (hs-tokens-of "{a{.a") "list") 3)) "CLASS_REF")
(assert= (hs-token-value (nth (get (hs-tokens-of "{a{.a") "list") 3)) ".a")
(assert= (hs-token-type (nth (get (hs-tokens-of "[a[.a") "list") 3)) "CLASS_REF")
(assert= (hs-token-value (nth (get (hs-tokens-of "[a[.a") "list") 3)) ".a")
)
(deftest "handles comments properly"
(error "SKIP (untranslated): handles comments properly"))
(assert= (len (get (hs-tokens-of "--") "list")) 0)
(assert= (len (get (hs-tokens-of "asdf--") "list")) 1)
(assert= (len (get (hs-tokens-of "-- asdf") "list")) 0)
(assert= (len (get (hs-tokens-of "--\nasdf") "list")) 1)
(assert= (len (get (hs-tokens-of "--\nasdf--") "list")) 1)
(assert= (len (get (hs-tokens-of "---asdf") "list")) 0)
(assert= (len (get (hs-tokens-of "----\n---asdf") "list")) 0)
(assert= (len (get (hs-tokens-of "----asdf----") "list")) 0)
(assert= (len (get (hs-tokens-of "---\nasdf---") "list")) 1)
(assert= (len (get (hs-tokens-of "// asdf") "list")) 0)
(assert= (len (get (hs-tokens-of "///asdf") "list")) 0)
(assert= (len (get (hs-tokens-of "asdf//") "list")) 1)
(assert= (len (get (hs-tokens-of "asdf\n//") "list")) 2)
)
(deftest "handles hex escapes properly"
(error "SKIP (untranslated): handles hex escapes properly"))
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\x1f\""))) (char-from-code 31))
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\x41\""))) "A")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"\\x41\\x61\""))) "Aa")
(let ((threw false))
(guard (e (true (set! threw true))) (hs-stream-consume (hs-tokens-of "\"\\x\"")))
(assert threw))
(let ((threw false))
(guard (e (true (set! threw true))) (hs-stream-consume (hs-tokens-of "\"\\xGG\"")))
(assert threw))
(let ((threw false))
(guard (e (true (set! threw true))) (hs-stream-consume (hs-tokens-of "\"\\x4\"")))
(assert threw))
)
(deftest "handles id references properly"
(error "SKIP (untranslated): handles id references properly"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "#a"))) "ID_REF")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "#a"))) "#a")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of " #a"))) "ID_REF")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of " #a"))) "#a")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "a#a"))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "a#a"))) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "(a)#a") "list") 4)) "IDENTIFIER")
(assert= (hs-token-value (nth (get (hs-tokens-of "(a)#a") "list") 4)) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "{a}#a") "list") 4)) "IDENTIFIER")
(assert= (hs-token-value (nth (get (hs-tokens-of "{a}#a") "list") 4)) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "[a]#a") "list") 4)) "IDENTIFIER")
(assert= (hs-token-value (nth (get (hs-tokens-of "[a]#a") "list") 4)) "a")
(assert= (hs-token-type (nth (get (hs-tokens-of "(a(#a") "list") 3)) "ID_REF")
(assert= (hs-token-value (nth (get (hs-tokens-of "(a(#a") "list") 3)) "#a")
(assert= (hs-token-type (nth (get (hs-tokens-of "{a{#a") "list") 3)) "ID_REF")
(assert= (hs-token-value (nth (get (hs-tokens-of "{a{#a") "list") 3)) "#a")
(assert= (hs-token-type (nth (get (hs-tokens-of "[a[#a") "list") 3)) "ID_REF")
(assert= (hs-token-value (nth (get (hs-tokens-of "[a[#a") "list") 3)) "#a")
)
(deftest "handles identifiers properly"
(error "SKIP (untranslated): handles identifiers properly"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "foo"))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "foo"))) "foo")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of " foo "))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of " foo "))) "foo")
(let ((s (hs-tokens-of " foo bar")))
(let ((tok1 (hs-stream-consume s)))
(assert= (hs-token-type tok1) "IDENTIFIER")
(assert= (hs-token-value tok1) "foo")
(let ((tok2 (hs-stream-consume s)))
(assert= (hs-token-type tok2) "IDENTIFIER")
(assert= (hs-token-value tok2) "bar"))))
(let ((s (hs-tokens-of " foo\n-- a comment\n bar")))
(let ((tok1 (hs-stream-consume s)))
(assert= (hs-token-type tok1) "IDENTIFIER")
(assert= (hs-token-value tok1) "foo")
(let ((tok2 (hs-stream-consume s)))
(assert= (hs-token-type tok2) "IDENTIFIER")
(assert= (hs-token-value tok2) "bar"))))
)
(deftest "handles identifiers with numbers properly"
(error "SKIP (untranslated): handles identifiers with numbers properly"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "f1oo"))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "f1oo"))) "f1oo")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "fo1o"))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "fo1o"))) "fo1o")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "foo1"))) "IDENTIFIER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "foo1"))) "foo1")
)
(deftest "handles look ahead property"
(error "SKIP (untranslated): handles look ahead property"))
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "a 1 + 1") 0)) "a")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "a 1 + 1") 1)) "1")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "a 1 + 1") 2)) "+")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "a 1 + 1") 3)) "1")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "a 1 + 1") 4)) "<<<EOF>>>")
)
(deftest "handles numbers properly"
(error "SKIP (untranslated): handles numbers properly"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1"))) "1")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1.1"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1.1"))) "1.1")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1234567890.1234567890"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1234567890.1234567890"))) "1234567890.1234567890")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1e6"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1e6"))) "1e6")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1e-6"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1e-6"))) "1e-6")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1.1e6"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1.1e6"))) "1.1e6")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "1.1e-6"))) "NUMBER")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "1.1e-6"))) "1.1e-6")
(assert= (hs-token-type (nth (get (hs-tokens-of "1.1.1") "list") 0)) "NUMBER")
(assert= (hs-token-type (nth (get (hs-tokens-of "1.1.1") "list") 1)) "PERIOD")
(assert= (hs-token-type (nth (get (hs-tokens-of "1.1.1") "list") 2)) "NUMBER")
(assert= (len (get (hs-tokens-of "1.1.1") "list")) 3)
)
(deftest "handles operators properly"
(error "SKIP (untranslated): handles operators properly"))
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "+"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "+"))) "+")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "-"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "-"))) "-")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "*"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "*"))) "*")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "."))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "."))) ".")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "\\"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\\"))) "\\")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of ":"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ":"))) ":")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "%"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "%"))) "%")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "|"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "|"))) "|")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "!"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "!"))) "!")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "?"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "?"))) "?")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "#"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "#"))) "#")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "&"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "&"))) "&")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of ";"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ";"))) ";")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of ","))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ","))) ",")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "("))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "("))) "(")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of ")"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ")"))) ")")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "<"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "<"))) "<")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of ">"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ">"))) ">")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "{"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "{"))) "{")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "}"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "}"))) "}")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "["))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "["))) "[")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "]"))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "]"))) "]")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "="))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "="))) "=")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "<="))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "<="))) "<=")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of ">="))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of ">="))) ">=")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "=="))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "=="))) "==")
(assert= (hs-token-op? (hs-stream-consume (hs-tokens-of "==="))) true)
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "==="))) "===")
)
(deftest "handles strings properly"
(error "SKIP (untranslated): handles strings properly"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "\"foo\""))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"foo\""))) "foo")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "\"fo'o\""))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"fo'o\""))) "fo'o")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "\"fo\\\"o\""))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "\"fo\\\"o\""))) "fo\"o")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "'foo'"))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "'foo'"))) "foo")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "'fo\"o'"))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "'fo\"o'"))) "fo\"o")
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "'fo\\'o'"))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "'fo\\'o'"))) "fo'o")
(let ((threw false))
(guard (e (true (set! threw true))) (hs-stream-consume (hs-tokens-of "'")))
(assert threw))
(let ((threw false))
(guard (e (true (set! threw true))) (hs-stream-consume (hs-tokens-of "\"")))
(assert threw))
)
(deftest "handles strings properly 2"
(error "SKIP (untranslated): handles strings properly 2"))
(assert= (hs-token-type (hs-stream-consume (hs-tokens-of "'foo'"))) "STRING")
(assert= (hs-token-value (hs-stream-consume (hs-tokens-of "'foo'"))) "foo")
)
(deftest "handles template bootstrap properly"
(error "SKIP (untranslated): handles template bootstrap properly"))
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"" :template) 0)) "\"")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"$" :template) 0)) "\"")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"$" :template) 1)) "$")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${" :template) 0)) "\"")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${" :template) 1)) "$")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${" :template) 2)) "{")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"" :template) 0)) "\"")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"" :template) 1)) "$")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"" :template) 2)) "{")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"" :template) 3)) "asdf")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"}\"" :template) 0)) "\"")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"}\"" :template) 1)) "$")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"}\"" :template) 2)) "{")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"}\"" :template) 3)) "asdf")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"}\"" :template) 4)) "}")
(assert= (hs-token-value (hs-stream-token (hs-tokens-of "\"${\"asdf\"}\"" :template) 5)) "\"")
)
(deftest "handles whitespace properly"
(error "SKIP (untranslated): handles whitespace properly"))
(assert= (len (get (hs-tokens-of " ") "list")) 0)
(assert= (len (get (hs-tokens-of " asdf") "list")) 1)
(assert= (len (get (hs-tokens-of " asdf ") "list")) 2)
(assert= (len (get (hs-tokens-of "asdf ") "list")) 2)
(assert= (len (get (hs-tokens-of "\n") "list")) 0)
(assert= (len (get (hs-tokens-of "\nasdf") "list")) 1)
(assert= (len (get (hs-tokens-of "\nasdf\n") "list")) 2)
(assert= (len (get (hs-tokens-of "asdf\n") "list")) 2)
(assert= (len (get (hs-tokens-of "\r") "list")) 0)
(assert= (len (get (hs-tokens-of "\rasdf") "list")) 1)
(assert= (len (get (hs-tokens-of "\rasdf\r") "list")) 2)
(assert= (len (get (hs-tokens-of "asdf\r") "list")) 2)
(assert= (len (get (hs-tokens-of "\t") "list")) 0)
(assert= (len (get (hs-tokens-of "\tasdf") "list")) 1)
(assert= (len (get (hs-tokens-of "\tasdf\t") "list")) 2)
(assert= (len (get (hs-tokens-of "asdf\t") "list")) 2)
)
(deftest "string interpolation isnt surprising"
(hs-cleanup!)
(let ((_el-div (dom-create-element "div")))
(dom-set-attr _el-div "_" "on click set x to 42 then put `test${x} test ${x} test$x test $x test $x test ${x} test$x test_$x test_${x} test-$x test.$x` into my.innerHTML")
(dom-set-attr _el-div "_" "on click set x to 42 then put `test\\${x} test ${x} test\\$x test $x test \\$x test \\${x} test$x test_$x test_${x} test-$x test.$x` into my.innerHTML")
(dom-append (dom-body) _el-div)
(hs-activate! _el-div)
(dom-dispatch _el-div "click" nil)