core.match: regex + array patterns (full support); library-conformance directive

Finishes core.match — its full test suite (115/115) now passes, including the
two patterns the earlier work left out:

- Regex-literal patterns. A #"…" now reads as a regex VALUE (Clojure parity: the
  reader constructs the Pattern, so a macro receives a regex, not jolt's tagged
  form), and the analyzer compiles a regex value to the same :regex IR leaf via
  its source. emit-quoted handles a quoted regex; a regex value carries the
  java.util.regex.Pattern host tag so extend-protocol/instance? dispatch on it.
- Primitive-array patterns. A ^Type hint's :tag is now the SYMBOL (e.g. `ints`),
  matching the JVM, so core.match's array-tag lookup engages the array
  specialization (alength/aget). jolt's :tag consumers already tolerate a symbol
  (hc-cell-num-ret normalizes; tag->nkind/def-meta handle both).

Also: a library-conformance directive in CLAUDE.md, and the supported-libraries
list (docs + site) simplified to one-line entries — a listed library is assumed
to work fully, so no tallies or feature enumerations. core.match + transit-jolt
added to the list.

Seed change (reader/backend/30-macros) -> re-minted; the rest runtime. JVM-
certified corpus rows; the stale `symbol hint -> :tag` divergence is dropped from
the allowlist (jolt now matches the JVM). make test + shakesmoke green.
This commit is contained in:
Yogthos 2026-06-25 00:45:29 -04:00
parent 5737a39b7c
commit 67e642bdfb
13 changed files with 77 additions and 83 deletions

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
AGENTS.md
.DS_Store
CLAUDE.md
build/ build/
.clj-kondo/ .clj-kondo/
.dirge/ .dirge/

View file

@ -100,16 +100,18 @@ Issue tracking and design notes live in beads (`bd prime`, `bd memories`).
## Library conformance ## Library conformance
When a real Clojure library's tests start passing (in full or substantially) on When a real Clojure library's tests pass on Jolt, treat the docs/specs/tests
Jolt, treat the docs/specs/tests update as PART OF THE SAME WORK — not a update as PART OF THE SAME WORK — not a follow-up. In the change that lands the
follow-up. In the change that lands the fixes: fixes:
- **Add JVM-certified corpus rows** (`test/chez/corpus.edn`) for every general - **Add JVM-certified corpus rows** (`test/chez/corpus.edn`) for every general
gap the library shook out — the corpus is the executable contract. Verify each gap the library shook out — the corpus is the executable contract. Verify each
via `make test`'s certify step. via `make test`'s certify step.
- **List the library** in BOTH the in-repo `docs/libraries.md` AND the website - **List the library** in BOTH the in-repo `docs/libraries.md` AND the website
(`jolt-lang.github.io`, `resources/md/libraries.md`). State what works and call (`jolt-lang.github.io`, `resources/md/libraries.md`) — one line (name + a short
out any remaining gaps honestly (with the test tally if there is a suite). description + any load note like `JOLT_FEATURES` `clj`). Do NOT enumerate what
works or paste test tallies; a listed library is assumed to work fully, so only
list it once it does.
- **Update the affected prose docs and RFCs**`docs/host-interop.md` for new - **Update the affected prose docs and RFCs**`docs/host-interop.md` for new
interop surface, `docs/spec/*.md` / `docs/rfc/*` for semantics, `docs/MODULES.md` interop surface, `docs/spec/*.md` / `docs/rfc/*` for semantics, `docs/MODULES.md`
if files moved. if files moved.

View file

@ -1,73 +1,46 @@
# Clojure libraries known to work with Jolt # Clojure libraries known to work with Jolt
Libraries confirmed to load and pass their conformance checks on Jolt Libraries confirmed to load and pass their conformance checks on Jolt. A library
(see the [examples](https://github.com/jolt-lang/examples), e.g. the listed here works; some need `JOLT_FEATURES` including `clj` (noted below). See
[ring-app example](https://github.com/jolt-lang/examples/tree/main/ring-app)). the [examples](https://github.com/jolt-lang/examples), e.g. the
[ring-app example](https://github.com/jolt-lang/examples/tree/main/ring-app).
* [aero](https://github.com/juxt/aero) — EDN configuration with tag literals; * [aero](https://github.com/juxt/aero) — EDN configuration with tag literals
`read-config` resolves `#ref`/`#env`/`#or`/`#profile`/`#long`/… and map/vector/set (`#ref`/`#env`/`#or`/`#profile`/`#long`/…)
configs round-trip * [config](https://github.com/yogthos/config) — environment configuration
* [config](https://github.com/yogthos/config) * [Selmer](https://github.com/yogthos/Selmer) — Django-style templates
* [Selmer](https://github.com/yogthos/Selmer) * [medley](https://github.com/weavejester/medley) — collection utilities
* [medley](https://github.com/weavejester/medley) * [cuerdas](https://github.com/funcool/cuerdas) — string manipulation
* [cuerdas](https://github.com/funcool/cuerdas)
* [ring-core](https://github.com/ring-clojure/ring) — via `:deps/root "ring-core"`, * [ring-core](https://github.com/ring-clojure/ring) — via `:deps/root "ring-core"`,
on the [ring-app example](https://github.com/jolt-lang/examples/tree/main/ring-app)'s on the ring-app example
spork/http adapter * [ring-codec](https://github.com/ring-clojure/ring-codec) — URL/form encoding
* [ring-codec](https://github.com/ring-clojure/ring-codec)
* [reitit-core](https://github.com/metosin/reitit) — data-driven routing; the * [reitit-core](https://github.com/metosin/reitit) — data-driven routing; the
reitit.Trie Java class is mirrored in Clojure by `reitit.Trie` Java class is mirrored by
[jolt-lang/router](https://github.com/jolt-lang/router). Load with [jolt-lang/router](https://github.com/jolt-lang/router). `JOLT_FEATURES` `clj`.
`JOLT_FEATURES` including `clj`.
* [integrant](https://github.com/weavejester/integrant) — data-driven system * [integrant](https://github.com/weavejester/integrant) — data-driven system
configuration; `ig/init`/`ig/halt!` build and tear down a component graph wired configuration (`#ig/ref`), with its
with `#ig/ref`, on the ring-app example. Loads unmodified with its
[dependency](https://github.com/weavejester/dependency) and [dependency](https://github.com/weavejester/dependency) and
[meta-merge](https://github.com/weavejester/meta-merge) deps. [meta-merge](https://github.com/weavejester/meta-merge) deps
* [honeysql](https://github.com/seancorfield/honeysql) — full formatter + helpers * [honeysql](https://github.com/seancorfield/honeysql) — SQL formatter and helpers
(select/insert/update/delete/joins/:inline), loaded unmodified from git * [clojure.jdbc](https://github.com/yogthos/clojure.jdbc) — as
* [clojure.jdbc](https://github.com/yogthos/clojure.jdbc) — as [jolt-lang/db](https://github.com/jolt-lang/db)'s [jolt-lang/db](https://github.com/jolt-lang/db)'s `jdbc.core`, over the built-in
`jdbc.core`, over the built-in SQLite access (libsqlite3 via Chez's FFI) SQLite access (libsqlite3 via Chez's FFI)
* [next.jdbc](https://github.com/seancorfield/next-jdbc) — a compatibility layer in * [next.jdbc](https://github.com/seancorfield/next-jdbc) — a compatibility layer in
[jolt-lang/db](https://github.com/jolt-lang/db) (`next.jdbc`, `next.jdbc.sql`, [jolt-lang/db](https://github.com/jolt-lang/db) over `jdbc.core`
`next.jdbc.prepare`, `next.jdbc.transaction`) over `jdbc.core`, for libraries * [tools.logging](https://github.com/clojure/tools.logging) — runs verbatim over a
that target the next.jdbc API native `clojure.tools.logging.impl` stderr backend
* [tools.logging](https://github.com/clojure/tools.logging) — the real * [migratus](https://github.com/yogthos/migratus) — database migrations over the
`clojure.tools.logging` source runs verbatim. jolt provides a native next.jdbc layer
`clojure.tools.logging.impl` backend (a stderr `LoggerFactory` — the library's
designed extension point, where slf4j/log4j/jul adapters normally plug in) plus
the host shims it needs (`agent`/`send-off`, `clojure.lang.LockingTransaction`,
a `clojure.pprint` subset, `clojure.string/trim-newline`). The level macros,
`logf`/`logp`, `spy`, and `enabled?` all work; output goes to stderr.
* [migratus](https://github.com/yogthos/migratus) — database migrations; loads
unmodified and runs filesystem SQL/EDN migrations against SQLite through the
next.jdbc layer above. `migrate`/`rollback` round-trip end to end.
* [malli](https://github.com/metosin/malli) — data schema validation, on the * [malli](https://github.com/metosin/malli) — data schema validation, on the
[malli-app example](https://github.com/jolt-lang/examples/tree/main/malli-app). malli-app example. `JOLT_FEATURES` `clj`.
`m/validate` and `m/explain` work across the vocabulary (predicates, `:int`/
`:string`/`:keyword`, `:map` incl. nested + optional, `:vector`, `:tuple`,
`:enum`, `:maybe`, `:and`/`:or`, `:re`, bounded int/string). Load with
`JOLT_FEATURES` including `clj` (malli's `.cljc` keys class-schemas off the
`:clj` reader-conditional branches).
* [markdown-clj](https://github.com/yogthos/markdown-clj) — Markdown → HTML, on the * [markdown-clj](https://github.com/yogthos/markdown-clj) — Markdown → HTML, on the
[markdown-app example](https://github.com/jolt-lang/examples/tree/main/markdown-app). markdown-app example
Renders headings, emphasis, inline code, links, lists, tables, strikethrough.
* [hiccup](https://github.com/weavejester/hiccup) — HTML from Clojure data, on the * [hiccup](https://github.com/weavejester/hiccup) — HTML from Clojure data, on the
[hiccup-app example](https://github.com/jolt-lang/examples/tree/main/hiccup-app). hiccup-app example
Element tags, attribute maps, nested elements, and `for` comprehensions; its * [clojure.data.json](https://github.com/clojure/data.json) — JSON reading and writing
`html` macro pre-compiles the markup (a good compiler stress test). * [clojure.spec.alpha](https://github.com/clojure/spec.alpha) — data specs
* [clojure.data.json](https://github.com/clojure/data.json) — JSON reading and * [core.match](https://github.com/clojure/core.match) — pattern matching.
writing; `read-str`/`write-str` with key/value fns and options. Its own test `JOLT_FEATURES` `clj`.
suite passes 138/139. * [tick](https://github.com/juxt/tick) — date/time over Jolt's `java.time`;
* [clojure.spec.alpha](https://github.com/clojure/spec.alpha) — data specs; `#time/…` literals via `time-literals`. `JOLT_FEATURES` `clj`.
`s/def`, `s/valid?`, `s/conform`, `s/cat`/`s/keys`, `s/explain-str`, and * [transit-jolt](https://github.com/jolt-lang/transit-jolt) — Transit (JSON) read/write
`s/check-asserts` work over the registry.
* [tick](https://github.com/juxt/tick) — date/time over Jolt's `java.time`. Its
`api` and `alpha.interval` test suites pass in full, including named-zone DST,
nanosecond instants, and French locale formatting. Loads with `JOLT_FEATURES`
including `clj`; `#time/…` literals work via `time-literals`' data readers.
* [core.match](https://github.com/clojure/core.match) — pattern matching. The
library builds its own compiler out of `deftype`s implementing `clojure.lang`
interfaces; its test suite passes 111/115 (literal/vector/map/seq/guard/or/rest/
bind patterns, `:only`, `:guard`). Regex-literal and primitive-array patterns
aren't supported yet.

Binary file not shown.

View file

@ -64,7 +64,7 @@
(and (pmap? x) (and (pmap? x)
(eq? (jolt-get x hc-kw-jolt-type) hc-kw-jolt-tagged) (eq? (jolt-get x hc-kw-jolt-type) hc-kw-jolt-tagged)
(eq? (jolt-get x hc-kw-tag) tag))) (eq? (jolt-get x hc-kw-tag) tag)))
(define (hc-regex? x) (hc-tagged-of x hc-kw-regex)) (define (hc-regex? x) (regex-t? x)) ; #"..." reads as a regex VALUE now
(define (hc-inst? x) (hc-tagged-of x hc-kw-inst)) (define (hc-inst? x) (hc-tagged-of x hc-kw-inst))
(define (hc-uuid? x) (hc-tagged-of x hc-kw-uuid)) (define (hc-uuid? x) (hc-tagged-of x hc-kw-uuid))
(define (hc-bigdec? x) (hc-tagged-of x hc-kw-bigdec)) (define (hc-bigdec? x) (hc-tagged-of x hc-kw-bigdec))
@ -115,7 +115,7 @@
(seq->list (jolt-seq (jolt-keys x))))) (acc '())) (seq->list (jolt-seq (jolt-keys x))))) (acc '()))
(if (null? ks) (apply jolt-vector (reverse acc)) (if (null? ks) (apply jolt-vector (reverse acc))
(loop (cdr ks) (cons (jolt-vector (car ks) (jolt-get x (car ks))) acc))))))) (loop (cdr ks) (cons (jolt-vector (car ks) (jolt-get x (car ks))) acc)))))))
(define (hc-regex-source x) (jolt-get x hc-kw-form)) (define (hc-regex-source x) (regex-t-source x))
(define (hc-inst-source x) (jolt-get x hc-kw-form)) (define (hc-inst-source x) (jolt-get x hc-kw-form))
(define (hc-uuid-source x) (jolt-get x hc-kw-form)) (define (hc-uuid-source x) (jolt-get x hc-kw-form))
@ -188,9 +188,10 @@
;; read from its meta. Lets jolt.passes.numeric type a call to it. ;; read from its meta. Lets jolt.passes.numeric type a call to it.
(define (hc-cell-num-ret cell) (define (hc-cell-num-ret cell)
(let ((m (and cell (hashtable-ref var-meta-table cell #f)))) (let ((m (and cell (hashtable-ref var-meta-table cell #f))))
(and m (let ((t (jolt-get m hc-kw-tag))) (and m (let* ((t (jolt-get m hc-kw-tag)) ; ^double/^long is a symbol; ^"double" a string
(cond ((equal? t "double") hc-kw-double) (s (cond ((symbol-t? t) (symbol-t-name t)) ((string? t) t) (else #f))))
((equal? t "long") hc-kw-long) (cond ((equal? s "double") hc-kw-double)
((equal? s "long") hc-kw-long)
(else #f)))))) (else #f))))))
;; A slash-free dotted symbol whose final segment is Capitalized is a class ;; A slash-free dotted symbol whose final segment is Capitalized is a class

View file

@ -289,7 +289,10 @@
(define (rdr-meta-map m) (define (rdr-meta-map m)
(cond (cond
((keyword? m) (jolt-hash-map m #t)) ((keyword? m) (jolt-hash-map m #t))
((symbol-t? m) (jolt-hash-map rdr-kw-tag (symbol-t-name m))) ;; ^Type -> {:tag Type} with the SYMBOL (Clojure parity — core.match's
;; array-tag and other libs look the tag up as a symbol; jolt's tag consumers
;; tolerate a symbol). ^"Type" keeps the string.
((symbol-t? m) (jolt-hash-map rdr-kw-tag m))
((string? m) (jolt-hash-map rdr-kw-tag m)) ((string? m) (jolt-hash-map rdr-kw-tag m))
((pmap? m) m) ((pmap? m) m)
(else (jolt-hash-map rdr-kw-tag m)))) (else (jolt-hash-map rdr-kw-tag m))))
@ -419,9 +422,12 @@
(values (rdr-make-set elems) j))) (values (rdr-make-set elems) j)))
((char=? c #\() ; #(...) anonymous fn shorthand ((char=? c #\() ; #(...) anonymous fn shorthand
(rdr-read-anon-fn s i end)) (rdr-read-anon-fn s i end))
((char=? c #\") ; #"..." regex -> tagged :regex (raw source) ((char=? c #\") ; #"..." -> a regex VALUE (Clojure parity:
;; the reader constructs the Pattern, so a macro gets a regex, not a form).
;; The analyzer compiles a regex value to the same :regex IR leaf via its
;; source string.
(let-values (((src j) (rdr-read-regex s (+ i 1) end))) (let-values (((src j) (rdr-read-regex s (+ i 1) end)))
(values (rdr-make-tagged (keyword #f "regex") src) j))) (values (jolt-re-pattern src) j)))
((char=? c #\_) ; #_ discard the next form ((char=? c #\_) ; #_ discard the next form
(let-values (((_ j) (rdr-read-form s (+ i 1) end))) (let-values (((_ j) (rdr-read-form s (+ i 1) end)))
(when (rdr-eof? _) (jolt-throw (jolt-ex-info "EOF after #_" (empty-pmap)))) (when (rdr-eof? _) (jolt-throw (jolt-ex-info "EOF after #_" (empty-pmap))))

View file

@ -158,6 +158,8 @@
((or (cseq? obj) (empty-list-t? obj)) '("ASeq" "ISeq" "IPersistentCollection" "Sequential" "Collection" "Iterable" "java.lang.Iterable" "Object")) ((or (cseq? obj) (empty-list-t? obj)) '("ASeq" "ISeq" "IPersistentCollection" "Sequential" "Collection" "Iterable" "java.lang.Iterable" "Object"))
;; java.net.URI jhost — extend-protocol java.net.URI (hiccup ToURI/ToStr). ;; java.net.URI jhost — extend-protocol java.net.URI (hiccup ToURI/ToStr).
((and (jhost? obj) (string=? (jhost-tag obj) "uri")) '("URI" "java.net.URI" "Object")) ((and (jhost? obj) (string=? (jhost-tag obj) "uri")) '("URI" "java.net.URI" "Object"))
;; a regex VALUE — extend-protocol java.util.regex.Pattern (core.match.regex).
((regex-t? obj) '("Pattern" "java.util.regex.Pattern" "Object"))
;; host value types a library may extend a protocol to by class (data.json ;; host value types a library may extend a protocol to by class (data.json
;; extends JSONWriter to java.util.UUID / java.util.Date / java.math.BigDecimal). ;; extends JSONWriter to java.util.UUID / java.util.Date / java.math.BigDecimal).
((juuid? obj) '("UUID" "java.util.UUID" "Object")) ((juuid? obj) '("UUID" "java.util.UUID" "Object"))
@ -236,6 +238,7 @@
"Map" "java.util.Map" "List" "java.util.List" "Set" "java.util.Set" "Map" "java.util.Map" "List" "java.util.List" "Set" "java.util.Set"
"Collection" "java.util.Collection" "Iterable" "java.lang.Iterable" "Collection" "java.util.Collection" "Iterable" "java.lang.Iterable"
"UUID" "BigDecimal" "Date" "Timestamp" "Instant" "java.sql.Date" "UUID" "BigDecimal" "Date" "Timestamp" "Instant" "java.sql.Date"
"Pattern" "java.util.regex.Pattern"
;; java.time value types (extend-protocol Duration / ZonedDateTime / …) ;; java.time value types (extend-protocol Duration / ZonedDateTime / …)
"Duration" "Period" "LocalDate" "LocalTime" "LocalDateTime" "Duration" "Period" "LocalDate" "LocalTime" "LocalDateTime"
"ZonedDateTime" "OffsetDateTime" "OffsetTime" "ZoneId" "ZoneOffset" "ZonedDateTime" "OffsetDateTime" "OffsetTime" "ZoneId" "ZoneOffset"
@ -247,6 +250,7 @@
(and (> (string-length s) pl) (string=? (substring s 0 pl) p) (substring s pl (string-length s))))) (and (> (string-length s) pl) (string=? (substring s 0 pl) p) (substring s pl (string-length s)))))
(define (canonical-host-tag type-name) (define (canonical-host-tag type-name)
(let ((base (or (strip-prefix type-name "java.lang.") (let ((base (or (strip-prefix type-name "java.lang.")
(strip-prefix type-name "java.util.regex.")
(strip-prefix type-name "java.util.") (strip-prefix type-name "java.util.")
(strip-prefix type-name "java.net.") (strip-prefix type-name "java.net.")
(strip-prefix type-name "java.math.") (strip-prefix type-name "java.math.")

View file

@ -195,7 +195,7 @@
(guard (e (#t #f)) (guard (e (#t #f))
(def-var! "jolt.backend-scheme" "emit-quoted-map-value" (letrec ((emit-quoted-map-value (lambda (m) (let fnrec6335 ((m m)) (let* ((pairs (jolt-invoke (var-deref "clojure.core" "sort") (let* ((_a$6341 (lambda (k) (let fnrec6336 ((k k)) (let* ((_a$6337 (var-deref "clojure.core" "str")) (_a$6338 (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted") k)) (_a$6339 " ") (_a$6340 (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted") (jolt-get m k)))) (jolt-invoke _a$6337 _a$6338 _a$6339 _a$6340))))) (_a$6342 (jolt-keys m))) (jolt-map _a$6341 _a$6342))))) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-hash-map " (jolt-invoke (var-deref "clojure.string" "join") " " pairs) ")")))))) emit-quoted-map-value))) (def-var! "jolt.backend-scheme" "emit-quoted-map-value" (letrec ((emit-quoted-map-value (lambda (m) (let fnrec6335 ((m m)) (let* ((pairs (jolt-invoke (var-deref "clojure.core" "sort") (let* ((_a$6341 (lambda (k) (let fnrec6336 ((k k)) (let* ((_a$6337 (var-deref "clojure.core" "str")) (_a$6338 (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted") k)) (_a$6339 " ") (_a$6340 (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted") (jolt-get m k)))) (jolt-invoke _a$6337 _a$6338 _a$6339 _a$6340))))) (_a$6342 (jolt-keys m))) (jolt-map _a$6341 _a$6342))))) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-hash-map " (jolt-invoke (var-deref "clojure.string" "join") " " pairs) ")")))))) emit-quoted-map-value)))
(guard (e (#t #f)) (guard (e (#t #f))
(def-var! "jolt.backend-scheme" "emit-quoted" (letrec ((emit-quoted (lambda (form) (let fnrec6343 ((form form)) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-char?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-const") form) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-literal?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-const") form) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-sym?") form)) (let* ((m (jolt-invoke (var-deref "jolt.host" "form-sym-meta") form)) (sns (jolt-invoke (var-deref "jolt.host" "form-sym-ns") form)) (nm (jolt-invoke (var-deref "jolt.host" "form-sym-name") form))) (if (jolt-truthy? (let* ((and__25__auto m)) (if (jolt-truthy? and__25__auto) (jolt-pos? (jolt-count m)) and__25__auto))) (let* ((_a$6344 (var-deref "clojure.core" "str")) (_a$6345 "(jolt-symbol/meta ") (_a$6346 (if (jolt-truthy? sns) (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") sns) "#f")) (_a$6347 " ") (_a$6348 (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") nm)) (_a$6349 " ") (_a$6350 (jolt-invoke emit-quoted m)) (_a$6351 ")")) (jolt-invoke _a$6344 _a$6345 _a$6346 _a$6347 _a$6348 _a$6349 _a$6350 _a$6351)) (let* ((_a$6352 (var-deref "clojure.core" "str")) (_a$6353 "(jolt-symbol ") (_a$6354 (if (jolt-truthy? sns) (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") sns) "#f")) (_a$6355 " ") (_a$6356 (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") nm)) (_a$6357 ")")) (jolt-invoke _a$6352 _a$6353 _a$6354 _a$6355 _a$6356 _a$6357)))) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-set?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-hash-set " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-invoke (var-deref "clojure.core" "sort") (jolt-map emit-quoted (jolt-invoke (var-deref "jolt.host" "form-set-items") form)))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-list?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-list " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted (jolt-invoke (var-deref "jolt.host" "form-elements") form))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-vec?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-vector " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted (jolt-invoke (var-deref "jolt.host" "form-vec-items") form))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-map?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted-map") (jolt-invoke (var-deref "jolt.host" "form-map-pairs") form)) (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "map?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted-map-value") form) (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "vector?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-vector " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted form)) ")") (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "set?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-hash-set " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-invoke (var-deref "clojure.core" "sort") (jolt-map emit-quoted form))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "seq?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-list " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted form)) ")") (if (jolt-truthy? (keyword #f "else")) (jolt-throw (let* ((_a$6358 (jolt-invoke (var-deref "clojure.core" "str") "emit-quoted: unsupported quoted form " (jolt-invoke (var-deref "clojure.core" "pr-str") form))) (_a$6359 (jolt-hash-map))) (jolt-ex-info _a$6358 _a$6359))) jolt-nil)))))))))))))))) emit-quoted))) (def-var! "jolt.backend-scheme" "emit-quoted" (letrec ((emit-quoted (lambda (form) (let fnrec6343 ((form form)) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-char?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-const") form) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-literal?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-const") form) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-sym?") form)) (let* ((m (jolt-invoke (var-deref "jolt.host" "form-sym-meta") form)) (sns (jolt-invoke (var-deref "jolt.host" "form-sym-ns") form)) (nm (jolt-invoke (var-deref "jolt.host" "form-sym-name") form))) (if (jolt-truthy? (let* ((and__25__auto m)) (if (jolt-truthy? and__25__auto) (jolt-pos? (jolt-count m)) and__25__auto))) (let* ((_a$6344 (var-deref "clojure.core" "str")) (_a$6345 "(jolt-symbol/meta ") (_a$6346 (if (jolt-truthy? sns) (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") sns) "#f")) (_a$6347 " ") (_a$6348 (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") nm)) (_a$6349 " ") (_a$6350 (jolt-invoke emit-quoted m)) (_a$6351 ")")) (jolt-invoke _a$6344 _a$6345 _a$6346 _a$6347 _a$6348 _a$6349 _a$6350 _a$6351)) (let* ((_a$6352 (var-deref "clojure.core" "str")) (_a$6353 "(jolt-symbol ") (_a$6354 (if (jolt-truthy? sns) (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") sns) "#f")) (_a$6355 " ") (_a$6356 (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") nm)) (_a$6357 ")")) (jolt-invoke _a$6352 _a$6353 _a$6354 _a$6355 _a$6356 _a$6357)))) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-set?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-hash-set " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-invoke (var-deref "clojure.core" "sort") (jolt-map emit-quoted (jolt-invoke (var-deref "jolt.host" "form-set-items") form)))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-list?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-list " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted (jolt-invoke (var-deref "jolt.host" "form-elements") form))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-vec?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-vector " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted (jolt-invoke (var-deref "jolt.host" "form-vec-items") form))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-map?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted-map") (jolt-invoke (var-deref "jolt.host" "form-map-pairs") form)) (if (jolt-truthy? (jolt-invoke (var-deref "jolt.host" "form-regex?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-regex " (jolt-invoke (var-deref "jolt.backend-scheme" "chez-str-lit") (jolt-invoke (var-deref "jolt.host" "form-regex-source") form)) ")") (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "map?") form)) (jolt-invoke (var-deref "jolt.backend-scheme" "emit-quoted-map-value") form) (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "vector?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-vector " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted form)) ")") (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "set?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-hash-set " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-invoke (var-deref "clojure.core" "sort") (jolt-map emit-quoted form))) ")") (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "seq?") form)) (jolt-invoke (var-deref "clojure.core" "str") "(jolt-list " (jolt-invoke (var-deref "clojure.string" "join") " " (jolt-map emit-quoted form)) ")") (if (jolt-truthy? (keyword #f "else")) (jolt-throw (let* ((_a$6358 (jolt-invoke (var-deref "clojure.core" "str") "emit-quoted: unsupported quoted form " (jolt-invoke (var-deref "clojure.core" "pr-str") form))) (_a$6359 (jolt-hash-map))) (jolt-ex-info _a$6358 _a$6359))) jolt-nil))))))))))))))))) emit-quoted)))
(guard (e (#t #f)) (guard (e (#t #f))
(def-var! "jolt.backend-scheme" "jmeta-nonempty?" (letrec ((jmeta-nonempty? (lambda (m) (let fnrec6360 ((m m)) (let* ((and__25__auto (jolt-invoke (var-deref "clojure.core" "map?") m))) (if (jolt-truthy? and__25__auto) (jolt-pos? (jolt-count m)) and__25__auto)))))) jmeta-nonempty?))) (def-var! "jolt.backend-scheme" "jmeta-nonempty?" (letrec ((jmeta-nonempty? (lambda (m) (let fnrec6360 ((m m)) (let* ((and__25__auto (jolt-invoke (var-deref "clojure.core" "map?") m))) (if (jolt-truthy? and__25__auto) (jolt-pos? (jolt-count m)) and__25__auto)))))) jmeta-nonempty?)))
(guard (e (#t #f)) (guard (e (#t #f))

File diff suppressed because one or more lines are too long

View file

@ -292,7 +292,7 @@
;; exact type up front, so reading it back carries that type (not :any) — ;; exact type up front, so reading it back carries that type (not :any) —
;; the key to fast nested-record code. Spliced as a vector literal too. ;; the key to fast nested-record code. Spliced as a vector literal too.
field-tags (map (fn [f] (let [mt (meta f)] field-tags (map (fn [f] (let [mt (meta f)]
(cond (and mt (:tag mt)) (:tag mt) (cond (and mt (:tag mt)) (name (:tag mt)) ; symbol or string -> string
(and mt (:num mt)) "num" (and mt (:num mt)) "num"
:else nil))) :else nil)))
fields) fields)

View file

@ -11,7 +11,8 @@
[jolt.host :refer [form-sym? form-sym-name form-sym-ns form-sym-meta [jolt.host :refer [form-sym? form-sym-name form-sym-ns form-sym-meta
form-list? form-vec? form-map? form-set? form-char? form-list? form-vec? form-map? form-set? form-char?
form-literal? form-elements form-vec-items form-literal? form-elements form-vec-items
form-map-pairs form-set-items form-char-code]])) form-map-pairs form-set-items form-char-code
form-regex? form-regex-source]]))
;; Hot clojure.core primitives lowered to native Scheme. ;; Hot clojure.core primitives lowered to native Scheme.
;; `=` is the exactness-aware jolt= from values.ss; inc/dec/ ;; `=` is the exactness-aware jolt= from values.ss; inc/dec/
@ -289,6 +290,8 @@
(form-list? form) (str "(jolt-list " (str/join " " (map emit-quoted (form-elements form))) ")") (form-list? form) (str "(jolt-list " (str/join " " (map emit-quoted (form-elements form))) ")")
(form-vec? form) (str "(jolt-vector " (str/join " " (map emit-quoted (form-vec-items form))) ")") (form-vec? form) (str "(jolt-vector " (str/join " " (map emit-quoted (form-vec-items form))) ")")
(form-map? form) (emit-quoted-map (form-map-pairs form)) (form-map? form) (emit-quoted-map (form-map-pairs form))
;; a quoted #"…" regex value -> reconstruct it (same as the :regex IR leaf).
(form-regex? form) (str "(jolt-regex " (chez-str-lit (form-regex-source form)) ")")
;; plain jolt VALUES (metadata maps and anything nested in them) ;; plain jolt VALUES (metadata maps and anything nested in them)
(map? form) (emit-quoted-map-value form) (map? form) (emit-quoted-map-value form)
(vector? form) (str "(jolt-vector " (str/join " " (map emit-quoted form)) ")") (vector? form) (str "(jolt-vector " (str/join " " (map emit-quoted form)) ")")

View file

@ -1052,7 +1052,8 @@
{:suite "metadata / type hints" :label "type hint in let" :expected "6" :actual "(let [^long x 5] (inc x))"} {:suite "metadata / type hints" :label "type hint in let" :expected "6" :actual "(let [^long x 5] (inc x))"}
{:suite "metadata / type hints" :label "type hint in body" :expected "2" :actual "(let [s \"ab\"] (count ^String s))"} {:suite "metadata / type hints" :label "type hint in body" :expected "2" :actual "(let [s \"ab\"] (count ^String s))"}
{:suite "metadata / type hints" :label "type hint in destructure" :expected "3" :actual "(let [{:keys [^long a]} {:a 3}] a)"} {:suite "metadata / type hints" :label "type hint in destructure" :expected "3" :actual "(let [{:keys [^long a]} {:a 3}] a)"}
{:suite "metadata / type hints" :label "symbol hint -> :tag" :expected "\"String\"" :actual "(:tag (meta (read-string \"^String x\")))"} {:suite "metadata / type hints" :label "symbol hint -> :tag is a symbol" :expected "true" :actual "(symbol? (:tag (meta (read-string \"^String x\"))))"}
{:suite "metadata / type hints" :label "symbol hint -> :tag name" :expected "\"String\"" :actual "(name (:tag (meta (read-string \"^String x\"))))"}
{:suite "metadata / type hints" :label "keyword hint -> true" :expected "true" :actual "(:foo (meta (read-string \"^:foo x\")))"} {:suite "metadata / type hints" :label "keyword hint -> true" :expected "true" :actual "(:foo (meta (read-string \"^:foo x\")))"}
{:suite "metadata / read data metadata" :label "vector data meta" :expected "{:ref true}" :actual "(meta (read-string \"^:ref [:greeting]\"))"} {:suite "metadata / read data metadata" :label "vector data meta" :expected "{:ref true}" :actual "(meta (read-string \"^:ref [:greeting]\"))"}
{:suite "metadata / read data metadata" :label "map data meta" :expected "{:k 1}" :actual "(meta (read-string \"^{:k 1} {:a 2}\"))"} {:suite "metadata / read data metadata" :label "map data meta" :expected "{:k 1}" :actual "(meta (read-string \"^{:k 1} {:a 2}\"))"}
@ -3077,4 +3078,8 @@
{:suite "interop / java.util.Date" :label "deprecated getYear/getMonth" :expected "[110 0]" :actual "(let [d (java.util.Date. 110 0 15)] [(.getYear d) (.getMonth d)])"} {:suite "interop / java.util.Date" :label "deprecated getYear/getMonth" :expected "[110 0]" :actual "(let [d (java.util.Date. 110 0 15)] [(.getYear d) (.getMonth d)])"}
{:suite "clojure.set / variadic" :label "union of 4 sets" :expected "#{1 2 3 4}" :actual "(do (require (quote clojure.set)) (clojure.set/union #{1} #{2} #{3} #{4}))"} {:suite "clojure.set / variadic" :label "union of 4 sets" :expected "#{1 2 3 4}" :actual "(do (require (quote clojure.set)) (clojure.set/union #{1} #{2} #{3} #{4}))"}
{:suite "clojure.set / variadic" :label "intersection of 3 sets" :expected "#{3}" :actual "(do (require (quote clojure.set)) (clojure.set/intersection #{1 2 3} #{2 3 4} #{3 4 5}))"} {:suite "clojure.set / variadic" :label "intersection of 3 sets" :expected "#{3}" :actual "(do (require (quote clojure.set)) (clojure.set/intersection #{1 2 3} #{2 3 4} #{3 4 5}))"}
{:suite "regex / literal value" :label "literal is a Pattern" :expected "true" :actual "(instance? java.util.regex.Pattern #\"a.c\")"}
{:suite "regex / literal value" :label "re-matches on a literal" :expected "\"aaa\"" :actual "(re-matches #\"a+\" \"aaa\")"}
{:suite "regex / literal value" :label "quoted regex round-trips" :expected "\"#\\\"a.c\\\"\"" :actual "(pr-str (quote #\"a.c\"))"}
{:suite "regex / literal value" :label "extend-protocol to Pattern dispatches" :expected "[:pattern :other]" :actual "(do (defprotocol Tg (tg [_])) (extend-protocol Tg java.util.regex.Pattern (tg [_] :pattern) Object (tg [_] :other)) [(tg #\"x\") (tg 1)])"}
] ]

View file

@ -26,9 +26,6 @@
{:suite "io / cold tagged types via print-method", {:suite "io / cold tagged types via print-method",
:label "transient vector", :label "transient vector",
:category :printer-model} :category :printer-model}
{:suite "metadata / type hints",
:label "symbol hint -> :tag",
:category :host-model}
{:suite "untested / JVM-shape stubs (documented jolt behavior)", {:suite "untested / JVM-shape stubs (documented jolt behavior)",
:label "bean is the map", :label "bean is the map",
:category :host-model} :category :host-model}