More clojure.core coverage (real implementations, not stubs):
- transient/persistent!/conj!/assoc!/dissoc!/pop! as correctness-preserving
aliases (Jolt collections are persistent, so no in-place speedup but correct)
- unchecked-* arithmetic (Jolt numbers don't overflow -> plain ops)
- hash-combine/hash-ordered-coll/hash-unordered-coll (24-bit masked to stay
in integer range), ex-cause (ex-info now records a cause), prefers, random-uuid
Fix a pre-existing REPL bug: the set printer in main.janet iterated the backing
phm's table keys (:buckets/:cnt) instead of the elements, so every set printed
as #{:buckets :cnt} at the REPL (pr-str was already correct). Now uses phs-seq.
conformance 218/218, features 78/78, jank 120.
Round 3 of the persistent-collections work. Lists were immutable Janet arrays,
so conj/cons-prepend was an O(n) copy (O(n^2) to build a list) — a large perf
gap vs Clojure's PersistentList.
Add src/jolt/plist.janet: an immutable cons-cell list (first/rest/count), same
algorithm as Clojure/CLJS/jank PersistentList. conj/cons onto a list now creates
an O(1) node that shares the existing list as its tail (no copy), with a cached
O(1) count. Repeated conj is O(n) total instead of O(n^2).
Hooked plist through first/rest/next/seq/count/peek/pop/nth/empty/empty?, the
predicates (list?/seq?/coll?/sequential?), realize-for-iteration, =, coll->cells
(concat/lazy), both printers, destructuring, and instance? tags. (list ...) and
quoted lists stay arrays; only conj/cons introduce plist nodes, so the surface
and risk stay small.
Verified: reduce-conj of 200k elements runs in ~0.4s (was effectively O(n^2)).
conformance 206/206, features 78/78 (+7 list regressions), jank 120 (+1).
Round 2 of the persistent-collections work.
Add a real 32-way branching-trie persistent vector (src/jolt/pv.janet) with a
tail buffer: O(log32 n) conj/assoc/nth/pop, with unchanged subtrees shared by
identity. Vector literals and vec/vector/conj/assoc/subvec/etc. now produce and
maintain these in the default (immutable) build, replacing the old tuple-based
vectors. Every core seq op, the destructurer, IFn application, the printers, =,
and the evaluator's literal/splice paths were taught to handle the pvec type.
Define several Clojure seq fns that were silently leaking to Janet builtins
(some, keep, interleave, flatten, mapcat, interpose) and broke once vectors
became tables; normalize collections through realize-for-iteration everywhere.
Build-time JOLT_MUTABLE flag now selects fast Janet-native mutable collections:
in that mode vectors are arrays (conj appends in place, vector? true, print []),
sharing one representation with lists. Default build is immutable.
Tests: conformance 206/206, features 71/71, jank 119 (baseline). Test helpers
normalized so Janet-level = compares against tuple literals regardless of repr.
The 2 test-load-sci failures (bit-clear/get-method) pre-date this work.
Janet's struct? returns true for tuples, causing print-value's
symbol-struct check to call (get tuple :jolt/type) which fails with
'expected integer key for tuple...got :name'.
Fix: reorder cond in print-value — check tuple? and array? before
struct? checks. Split (or tuple? array? struct? table?) into
individual arms so cond stops at the first match.
( range 10) now renders [0 1 2 3 4 5 6 7 8 9] instead of error.
315 ok, 2 fail (pre-existing, unchanged)
- print-value now renders tuples as [1 2 3], arrays as (1 2 3),
structs/tables as {:k v}, sets as #{v}, keywords as :kw,
Jolt symbols as name or ns/name
- print-value uses prin (no trailing newline) for all scalars;
only adds newline at end of collection output
- print-collection recursively renders nested values
- ctx-set-current-ns "user" after init so REPL starts in user ns
- Forward var declaration for mutual recursion between
print-collection and print-value
Note: tuple/struct eval in piped REPL fails due to pre-existing
evaluator issue ("expected integer key for tuple") — this is
NOT caused by the print changes. Scalars render correctly.
315 tests pass, 0 regressions.
- print-value now renders tuples as [val1 val2 ...]
- print-value now renders arrays as (val1 val2 ...)
- print-value now renders structs/tables as {key val ...}
- print-value now renders sets as #{val1 val2 ...}
- print-value renders keywords with : prefix
- Forward var declaration for mutual recursion (print-collection → print-value)
- 315 tests pass, 0 regressions