Merge pull request #203 from jolt-lang/docs/libraries-conformance-directive
core.match: full support (regex + array patterns) + library-conformance directive
This commit is contained in:
commit
16528e8637
14 changed files with 70 additions and 313 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +1,6 @@
|
||||||
|
AGENTS.md
|
||||||
|
.DS_Store
|
||||||
|
CLAUDE.md
|
||||||
build/
|
build/
|
||||||
.clj-kondo/
|
.clj-kondo/
|
||||||
.dirge/
|
.dirge/
|
||||||
|
|
|
||||||
96
AGENTS.md
96
AGENTS.md
|
|
@ -1,96 +0,0 @@
|
||||||
# Agent Instructions
|
|
||||||
|
|
||||||
This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context.
|
|
||||||
|
|
||||||
> **Architecture in one line:** Issues live in a local Dolt database
|
|
||||||
> (`.beads/dolt/`); cross-machine sync uses `bd dolt push/pull` (a
|
|
||||||
> git-compatible protocol), stored under `refs/dolt/data` on your git
|
|
||||||
> remote — separate from `refs/heads/*` where your code lives.
|
|
||||||
> `.beads/issues.jsonl` is a passive export, not the wire protocol.
|
|
||||||
>
|
|
||||||
> See [SYNC_CONCEPTS.md](https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md)
|
|
||||||
> for the one-screen overview and anti-patterns (don't treat JSONL as the
|
|
||||||
> source of truth; don't `bd import` during normal operation; don't
|
|
||||||
> reach for third-party Dolt hosting before trying the default).
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bd ready # Find available work
|
|
||||||
bd show <id> # View issue details
|
|
||||||
bd update <id> --claim # Claim work atomically
|
|
||||||
bd close <id> # Complete work
|
|
||||||
bd dolt push # Push beads data to remote
|
|
||||||
```
|
|
||||||
|
|
||||||
## Non-Interactive Shell Commands
|
|
||||||
|
|
||||||
**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts.
|
|
||||||
|
|
||||||
Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input.
|
|
||||||
|
|
||||||
**Use these forms instead:**
|
|
||||||
```bash
|
|
||||||
# Force overwrite without prompting
|
|
||||||
cp -f source dest # NOT: cp source dest
|
|
||||||
mv -f source dest # NOT: mv source dest
|
|
||||||
rm -f file # NOT: rm file
|
|
||||||
|
|
||||||
# For recursive operations
|
|
||||||
rm -rf directory # NOT: rm -r directory
|
|
||||||
cp -rf source dest # NOT: cp -r source dest
|
|
||||||
```
|
|
||||||
|
|
||||||
**Other commands that may prompt:**
|
|
||||||
- `scp` - use `-o BatchMode=yes` for non-interactive
|
|
||||||
- `ssh` - use `-o BatchMode=yes` to fail instead of prompting
|
|
||||||
- `apt-get` - use `-y` flag
|
|
||||||
- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var
|
|
||||||
|
|
||||||
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:7510c1e2 -->
|
|
||||||
## Beads Issue Tracker
|
|
||||||
|
|
||||||
This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.
|
|
||||||
|
|
||||||
### Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bd ready # Find available work
|
|
||||||
bd show <id> # View issue details
|
|
||||||
bd update <id> --claim # Claim work
|
|
||||||
bd close <id> # Complete work
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rules
|
|
||||||
|
|
||||||
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
|
|
||||||
- Run `bd prime` for detailed command reference and session close protocol
|
|
||||||
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
|
|
||||||
|
|
||||||
**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.
|
|
||||||
|
|
||||||
## Session Completion
|
|
||||||
|
|
||||||
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
|
||||||
|
|
||||||
**MANDATORY WORKFLOW:**
|
|
||||||
|
|
||||||
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
|
||||||
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
|
||||||
3. **Update issue status** - Close finished work, update in-progress items
|
|
||||||
4. **PUSH TO REMOTE** - This is MANDATORY:
|
|
||||||
```bash
|
|
||||||
git pull --rebase
|
|
||||||
git push
|
|
||||||
git status # MUST show "up to date with origin"
|
|
||||||
```
|
|
||||||
5. **Clean up** - Clear stashes, prune remote branches
|
|
||||||
6. **Verify** - All changes committed AND pushed
|
|
||||||
7. **Hand off** - Provide context for next session
|
|
||||||
|
|
||||||
**CRITICAL RULES:**
|
|
||||||
- Work is NOT complete until `git push` succeeds
|
|
||||||
- NEVER stop before pushing - that leaves work stranded locally
|
|
||||||
- NEVER say "ready to push when you are" - YOU must push
|
|
||||||
- If push fails, resolve and retry until it succeeds
|
|
||||||
<!-- END BEADS INTEGRATION -->
|
|
||||||
144
CLAUDE.md
144
CLAUDE.md
|
|
@ -1,144 +0,0 @@
|
||||||
# Project Instructions for AI Agents
|
|
||||||
|
|
||||||
This file provides instructions and context for AI coding agents working on this project.
|
|
||||||
|
|
||||||
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:7510c1e2 -->
|
|
||||||
## Beads Issue Tracker
|
|
||||||
|
|
||||||
This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.
|
|
||||||
|
|
||||||
### Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bd ready # Find available work
|
|
||||||
bd show <id> # View issue details
|
|
||||||
bd update <id> --claim # Claim work
|
|
||||||
bd close <id> # Complete work
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rules
|
|
||||||
|
|
||||||
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
|
|
||||||
- Run `bd prime` for detailed command reference and session close protocol
|
|
||||||
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
|
|
||||||
|
|
||||||
**Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.
|
|
||||||
|
|
||||||
## Session Completion
|
|
||||||
|
|
||||||
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
|
||||||
|
|
||||||
**MANDATORY WORKFLOW:**
|
|
||||||
|
|
||||||
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
|
||||||
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
|
||||||
3. **Update issue status** - Close finished work, update in-progress items
|
|
||||||
4. **PUSH TO REMOTE** - This is MANDATORY:
|
|
||||||
```bash
|
|
||||||
git pull --rebase
|
|
||||||
git push
|
|
||||||
git status # MUST show "up to date with origin"
|
|
||||||
```
|
|
||||||
5. **Clean up** - Clear stashes, prune remote branches
|
|
||||||
6. **Verify** - All changes committed AND pushed
|
|
||||||
7. **Hand off** - Provide context for next session
|
|
||||||
|
|
||||||
**CRITICAL RULES:**
|
|
||||||
- Work is NOT complete until `git push` succeeds
|
|
||||||
- NEVER stop before pushing - that leaves work stranded locally
|
|
||||||
- NEVER say "ready to push when you are" - YOU must push
|
|
||||||
- If push fails, resolve and retry until it succeeds
|
|
||||||
<!-- END BEADS INTEGRATION -->
|
|
||||||
|
|
||||||
|
|
||||||
## Build & Test
|
|
||||||
|
|
||||||
No build step — `bin/joltc` runs off the checked-in seed (`host/chez/seed/`).
|
|
||||||
The gate is pure Chez (+ Clojure for the JVM oracle).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bin/joltc -e EXPR # run a Clojure expression on Chez
|
|
||||||
make test # FULL gate (self-host + corpus + unit + smoke + certify)
|
|
||||||
make corpus # conformance corpus vs the JVM-sourced spec (floor 2678)
|
|
||||||
make unit # host-specific unit cases (test/chez/unit.edn)
|
|
||||||
make selfhost # bootstrap fixpoint (rebuild == checked-in seed)
|
|
||||||
make certify # JVM oracle (skips if clojure absent)
|
|
||||||
chez --script host/chez/run-corpus.ss # the corpus gate directly; JOLT_CORPUS_LIMIT=N for a fast stride
|
|
||||||
make remint # re-mint the seed after a seed-source change
|
|
||||||
```
|
|
||||||
|
|
||||||
**Re-mint after changing a seed source.** The reader (`host/chez/reader.ss`), the
|
|
||||||
analyzer/IR/backend (`jolt-core/jolt/*.clj`), or the `clojure.core` overlay
|
|
||||||
(`jolt-core/clojure/core/*.clj`) are baked into the seed — change one and run
|
|
||||||
`make remint` (iterates `host/chez/bootstrap.ss` to a byte-fixpoint) or `make
|
|
||||||
selfhost` fails. Runtime-only `host/chez/*.ss` shims do NOT need a re-mint.
|
|
||||||
|
|
||||||
**Run the gate with a REAL exit code.** `make test > /tmp/gate.out 2>&1; echo
|
|
||||||
"EXIT: $?"` — the final `OK: all gates passed` line must be present. CI
|
|
||||||
(`.github/workflows/tests.yml`) runs `make test` on every push/PR.
|
|
||||||
|
|
||||||
## Architecture Overview
|
|
||||||
|
|
||||||
Clojure on Chez Scheme — the sole substrate. A small Chez runtime
|
|
||||||
(`host/chez/*.ss`: value model, persistent collections, seqs, vars/ns, host
|
|
||||||
interop) hosts a portable Clojure overlay (`jolt-core/`): the
|
|
||||||
reader/analyzer/IR/backend (`jolt-core/jolt/`) and `clojure.core` in
|
|
||||||
dependency-ordered tiers (`jolt-core/clojure/core/NN-*.clj`, loaded in order:
|
|
||||||
00-syntax, 00-kernel, 10-seq, 20-coll, 25-sorted, 30-macros, 40-lazy, 50-io).
|
|
||||||
The stdlib namespaces (`clojure.string`/`set`/`walk`/`edn`/`pprint`/…) are
|
|
||||||
portable Clojure under `stdlib/clojure/`.
|
|
||||||
|
|
||||||
`bin/joltc` (`host/chez/cli.ss`) loads the checked-in seed
|
|
||||||
(`host/chez/seed/{prelude,image}.ss`) + the spine and compiles+evals on Chez
|
|
||||||
(read → analyze → IR → emit → eval). `host/chez/bootstrap.ss` rebuilds that seed
|
|
||||||
from source on pure Chez; the build is a self-hosting fixpoint (a rebuild
|
|
||||||
reproduces the checked-in seed byte-for-byte — `make selfhost`). The correctness
|
|
||||||
oracle is the JVM-sourced conformance corpus (`test/chez/corpus.edn`,
|
|
||||||
`test/conformance/`).
|
|
||||||
|
|
||||||
Issue tracking and design notes live in beads (`bd prime`, `bd memories`).
|
|
||||||
|
|
||||||
## Conventions & Patterns
|
|
||||||
|
|
||||||
- **A tier may only use macros from tiers that load before it.** Compile mode
|
|
||||||
expands macros at tier LOAD, so an `if-let` (30-macros) inside a 20-coll fn
|
|
||||||
breaks compiled init even though it passes when expanded lazily. Same ordering
|
|
||||||
for expander-called fns (empty?/keys/vals live in 00-syntax).
|
|
||||||
- **Never read your own wrapper's fields with `get`** in attached-ops values
|
|
||||||
(sorted colls): `get` on the wrapper IS the dispatched lookup and recurses
|
|
||||||
forever. Use `jolt.host/ref-get`.
|
|
||||||
- **Map literals with `:jolt/type` as a key** parse as tagged reader forms —
|
|
||||||
don't tag overlay value maps in source.
|
|
||||||
- **The compiler is reached from the runtime by `var-deref` string lookup.** The
|
|
||||||
`.ss` runtime calls into the cross-compiled compiler with
|
|
||||||
`(var-deref "jolt.analyzer" "analyze")` etc., and the compiler resolves its own
|
|
||||||
unqualified `jolt.host/…` refs the same way against `host-contract.ss`. So a
|
|
||||||
public `defn` with no in-Clojure callers may still be a live entry point — don't
|
|
||||||
treat it as dead. Only a private `defn-` with no callers is safe to remove.
|
|
||||||
- **A native `clojure.core` fn is a `(def-var! "clojure.core" "name" …)`** in a
|
|
||||||
`host/chez/*.ss`; the rest of core is the overlay (`jolt-core/clojure/core/*.clj`).
|
|
||||||
A few natives are re-asserted in `post-prelude.ss` so they win over the overlay.
|
|
||||||
See [docs/MODULES.md](docs/MODULES.md) for where a given fn lives, and
|
|
||||||
[docs/seed-overlay-registry.md](docs/seed-overlay-registry.md) for the shadowing
|
|
||||||
rule. Start at [docs/MODULES.md](docs/MODULES.md) to find a feature's files.
|
|
||||||
- **Fix latent bugs to match Clojure** rather than preserving them, with a
|
|
||||||
regression case. Match the JVM (or provide a superset); the JVM-sourced corpus
|
|
||||||
is the contract.
|
|
||||||
- **Gate every change**: `make test` with a real exit code (self-host fixpoint,
|
|
||||||
corpus floor, unit, cli smoke, certify). Re-mint if a seed source changed.
|
|
||||||
|
|
||||||
## Writing style (comments, docstrings, docs)
|
|
||||||
|
|
||||||
Write like a human maintainer of a serious open-source project. Plain, terse,
|
|
||||||
factual. Document how the code works *now* — what it does and why it matters.
|
|
||||||
|
|
||||||
- No LLM tells: drop "Note that", "It's worth noting", "Importantly", "simply",
|
|
||||||
"essentially", "in order to", "under the hood", and marketing words
|
|
||||||
("comprehensive", "robust", "seamless", "leverage", "powerful").
|
|
||||||
- No historical exposition (how the code used to work, porting notes, "the prior
|
|
||||||
X"), no internal issue IDs (`jolt-xxxx`) or milestone tags ("Phase N") in
|
|
||||||
comments or docstrings. The git history and beads hold that.
|
|
||||||
- Keep genuine semantic contrasts with JVM Clojure — those document real,
|
|
||||||
user-visible behavior.
|
|
||||||
- Don't restate the code; explain the non-obvious. Match the surrounding file's
|
|
||||||
comment density and tone.
|
|
||||||
|
|
@ -1,68 +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.
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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))))
|
||||||
|
|
|
||||||
|
|
@ -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.")
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)) ")")
|
||||||
|
|
|
||||||
|
|
@ -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)])"}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue