Clean up codebase: rename stdlib layer, strip porting residue, fix tooling
Rename src/jolt -> stdlib (the runtime-loaded layer; jolt-core stays the seed-baked layer) and update the loader / emit-image / doc paths. Drop dead code: the spike/ experiments, the duplicate clojuredocs-export.edn (json moves to tools/), the Janet-era jolt.http binding, and the orphaned persistent_vector.clj whose ns/path didn't even match. Strip porting residue from comments and docstrings across host/chez, jolt-core, stdlib, tests, and docs: internal issue ids, "Phase N" markers, and the "vs Janet" historical exposition, leaving present-tense descriptions and the real JVM-Clojure semantic contrasts. Same pass over the corpus suite labels. The seed is unchanged (docstrings/comments aren't emitted), so the self-host fixpoint and corpus are untouched. Port tools/spec_coverage.py off the dead janet probe to bin/joltc and regenerate coverage.md; drop the dead :host/janet rule from certify.clj and regenerate the conformance profile. Add docs/host-interop.md (the JVM shims and how to register your own host class from a library) and a writing-style note in CLAUDE.md. Stabilize the four racy concurrency corpus cases (future-cancel and agent send/send-off): give the future a sleeping body and the agent a slow action, so cancel reliably catches an in-flight future and deref reliably reads the pre-update snapshot. They certify deterministically now, so drop their :flaky allowlist entries and the orphaned legend.
This commit is contained in:
parent
c18f8087f0
commit
33eff7c7d8
112 changed files with 970 additions and 1621 deletions
|
|
@ -4,7 +4,7 @@
|
|||
;; redefinable. Loaded after the seq tier; self-hosted in compile mode.
|
||||
;;
|
||||
;; Same migration rule as the seq tier (see 10-seq.clj): not in core-renames, no
|
||||
;; internal Janet callers, not used by the self-hosted compiler.
|
||||
;; internal callers, not used by the self-hosted compiler.
|
||||
|
||||
;; Tiny leaves first — fns below in this tier (and 25-sorted) use them.
|
||||
(defn some? [x] (not (nil? x)))
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
;; overlay versions cost an extra call layer per element (seq-pipe bench 4x).
|
||||
|
||||
;; Variadic bit ops — canonical Clojure arities folding the binary host op
|
||||
;; (__bit-* seams). 2-arg call sites still compile to the native janet op via
|
||||
;; (__bit-* seams). 2-arg call sites still compile to the native op via
|
||||
;; the backend's native-ops table, so the binary fast path is unchanged.
|
||||
(defn bit-and
|
||||
([x y] (__bit-and x y))
|
||||
|
|
@ -87,8 +87,8 @@
|
|||
;; Distinct keys are recorded in a side vector so the buckets can be frozen in
|
||||
;; place (no second map rebuild). A bucket's FIRST element is stored as a cheap
|
||||
;; persistent [x]; only the second element promotes it to a transient — so an
|
||||
;; all-singletons grouping pays no transient alloc and matches the old cost,
|
||||
;; while any bucket that actually grows rides the O(1) push.
|
||||
;; all-singletons grouping pays no transient alloc, while any bucket that
|
||||
;; actually grows rides the O(1) push.
|
||||
(defn group-by [f coll]
|
||||
(let [tm (transient {})
|
||||
ks (reduce (fn [ks x]
|
||||
|
|
@ -355,7 +355,7 @@
|
|||
(make-hierarchy) (partition 2 deriv-seq))
|
||||
h))))
|
||||
|
||||
;; --- Stage 3 tier shrink: pure-over-core leaves moved off the host primitives ----
|
||||
;; --- pure-over-core leaves expressed off the host primitives -----------------
|
||||
|
||||
;; Representation predicates over the overlay's own predicates.
|
||||
(defn sequential? [x] (or (vector? x) (seq? x)))
|
||||
|
|
@ -364,7 +364,7 @@
|
|||
(or (vector? x) (map? x) (set? x) (list? x) (string? x)))
|
||||
(defn indexed? [x] (vector? x))
|
||||
;; sorted? is defined by the next tier (25-sorted) — declared here so this
|
||||
;; tier compiles (forward references are analysis errors now, jolt-2o7.3).
|
||||
;; tier compiles (forward references are analysis errors).
|
||||
(declare sorted?)
|
||||
|
||||
(defn reversible? [x] (or (vector? x) (sorted? x)))
|
||||
|
|
@ -377,7 +377,7 @@
|
|||
(defn infinite? [x] (and (number? x) (or (= x ##Inf) (= x ##-Inf))))
|
||||
|
||||
;; qualified-/simple- keyword?/symbol? moved above qualified-ident? (forward
|
||||
;; references are analysis errors now — jolt-2o7.3).
|
||||
;; references are analysis errors).
|
||||
|
||||
|
||||
;; realized?: defined on the pending types only (delay/lazy-seq/future read
|
||||
|
|
@ -453,7 +453,7 @@
|
|||
(defn println-str [& xs] (__with-out-str (fn* [] (apply println xs))))
|
||||
(defn prn-str [& xs] (__with-out-str (fn* [] (apply prn xs))))
|
||||
|
||||
;; --- Phase 2 leaf batch 4 (jolt-ded): over the rand / sort host seams --------
|
||||
;; --- leaves over the rand / sort host seams ----------------------------------
|
||||
|
||||
;; Canonical truncation toward zero via int (the kernel fn floored, which is
|
||||
;; wrong for a negative n).
|
||||
|
|
@ -549,11 +549,11 @@
|
|||
|
||||
;; file-seq: the tree of paths under root (root included), directories walked
|
||||
;; via the host dir primitives. Paths (strings), not File objects. (Lives below
|
||||
;; tree-seq: forward references are analysis errors now — jolt-2o7.3.)
|
||||
;; tree-seq: forward references are analysis errors.)
|
||||
(defn file-seq [root]
|
||||
(if (__file? root)
|
||||
;; java.io.File tree: walk via the File method surface so leaves are File
|
||||
;; values callers can invoke .isFile/.getName/slurp on (jolt-hjw).
|
||||
;; values callers can invoke .isFile/.getName/slurp on.
|
||||
(tree-seq (fn [f] (.isDirectory f)) (fn [f] (seq (.listFiles f))) root)
|
||||
(tree-seq __dir? __list-dir root)))
|
||||
|
||||
|
|
@ -587,10 +587,6 @@
|
|||
;; No ratio type on Jolt, so rationalize is identity.
|
||||
(defn rationalize [x] x)
|
||||
|
||||
;; trampoline: repeatedly calls f with args until a non-function result.
|
||||
|
||||
;; rand-int: random integer in [0, n). Uses Janet math/random.
|
||||
|
||||
;; 0-arg: a stateful transducer (tracks [seen? prev] in a volatile, so no sentinel
|
||||
;; value is needed). 1-arg: eager dedupe of consecutive equal elements.
|
||||
(defn dedupe
|
||||
|
|
@ -625,8 +621,7 @@
|
|||
;; canonical Clojure 1.11 shape (core.clj seq-to-map-for-destructuring):
|
||||
;; even pairs build a map (later keys win, as createAsIfByAssoc), a SINGLE
|
||||
;; element is returned as-is (the trailing-map calling convention), and an
|
||||
;; unpaired key past pairs throws. The old jolt version silently dropped the
|
||||
;; trailing element, losing (f {:b 2}) kwargs calls.
|
||||
;; unpaired key past pairs throws.
|
||||
(defn seq-to-map-for-destructuring [s]
|
||||
(if (next s)
|
||||
(loop [m {} xs (seq s)]
|
||||
|
|
@ -637,8 +632,8 @@
|
|||
m))
|
||||
(if (seq s) (first s) {})))
|
||||
|
||||
;; Phase 4 (jolt-1j0): host-coupled fns that are pure logic over existing core
|
||||
;; primitives, so they need no new jolt.host surface.
|
||||
;; Host-coupled fns that are pure logic over existing core primitives, so they
|
||||
;; need no new jolt.host surface.
|
||||
|
||||
;; vary-meta: f applied to obj's metadata (+ extra args), reattached. meta and
|
||||
;; with-meta are the irreducible host primitives; vary-meta is just their compose.
|
||||
|
|
@ -650,9 +645,8 @@
|
|||
(apply str (map (fn [c] (if (= c \-) \_ c)) (seq (str s)))))
|
||||
|
||||
;; reduce-kv over a map (k v) or vector (index v). Both branches go through reduce,
|
||||
;; so reduced short-circuits — and the vector path indexes correctly. (The prior
|
||||
;; Janet version saw a pvec as a table and folded over its internal keys; it also
|
||||
;; ignored reduced.) nil folds to init, matching Clojure.
|
||||
;; so reduced short-circuits — and the vector path indexes correctly. nil folds
|
||||
;; to init, matching Clojure.
|
||||
(defn reduce-kv [f init coll]
|
||||
(cond
|
||||
(vector? coll) (reduce (fn [acc i] (f acc i (nth coll i))) init (range (count coll)))
|
||||
|
|
@ -660,7 +654,7 @@
|
|||
(nil? coll) init
|
||||
:else (throw (str "reduce-kv not supported on: " coll))))
|
||||
|
||||
;; ex-info accessors. The Janet constructor (ex-info) stays — it builds the tagged
|
||||
;; ex-info accessors. The constructor (ex-info) stays native — it builds the tagged
|
||||
;; value and wires into throw — but the value exposes :jolt/type/:message/:data/
|
||||
;; :cause via get, so the accessors are pure over get. A thrown non-ex-info arrives
|
||||
;; wrapped as {:jolt/type :jolt/exception :value v}; unwrap that first.
|
||||
|
|
@ -724,7 +718,7 @@
|
|||
(when (< i (count vars))
|
||||
(var-set (nth vars i) (nth saved i))
|
||||
(recur (inc i))))))))
|
||||
;; Jolt has no chunked seqs (Phase 5 territory), so this is always false.
|
||||
;; Jolt has no chunked seqs, so this is always false.
|
||||
(defn chunked-seq? [x] false)
|
||||
|
||||
;; Atom peripheral operations. atom/swap!/reset!/deref stay native — the compiler
|
||||
|
|
@ -733,7 +727,7 @@
|
|||
;; slot; add-watch/remove-watch/set-validator! mutate the atom (or its watches
|
||||
;; sub-table) through the one host primitive jolt.host/ref-put! — the minimal
|
||||
;; mutation kernel the overlay can't express over core fns (a nil value removes the
|
||||
;; key). compare-and-set! compares by value, matching the prior Janet behavior.
|
||||
;; key). compare-and-set! compares by value.
|
||||
(defn swap-vals! [a f & args]
|
||||
(let [old (deref a)] [old (apply swap! a f args)]))
|
||||
(defn reset-vals! [a newval]
|
||||
|
|
@ -777,7 +771,7 @@
|
|||
(jolt.host/ref-put! target (nth idxs+val (- n 2)) val)
|
||||
val))
|
||||
|
||||
;; --- Phase 2 leaf batch (jolt-ded): fn combinators + host-free stubs ---------
|
||||
;; --- fn combinators + host-free stubs ----------------------------------------
|
||||
|
||||
(defn complement
|
||||
"Takes a fn f and returns a fn that takes the same arguments as f, has the
|
||||
|
|
@ -785,8 +779,7 @@
|
|||
[f]
|
||||
(fn [& args] (not (apply f args))))
|
||||
|
||||
;; Canonical Clojure fnil: patches only the FIRST 1-3 arguments (the old Janet
|
||||
;; kernel patched every position it had a default for, which Clojure does not).
|
||||
;; Canonical Clojure fnil: patches only the FIRST 1-3 arguments.
|
||||
(defn fnil
|
||||
([f x]
|
||||
(fn [a & args] (apply f (if (nil? a) x a) args)))
|
||||
|
|
@ -818,7 +811,7 @@
|
|||
(let [t (:test (meta v))]
|
||||
(if t (do (t) :ok) :no-test)))
|
||||
|
||||
;; --- Phase 2 leaf batch 2 (jolt-ded): canonical Clojure ports ----------------
|
||||
;; --- canonical Clojure ports -------------------------------------------------
|
||||
;; key/val/find first — merge-with and memoize below use them.
|
||||
|
||||
;; Strict, as in Clojure: an entry is what (seq m) yields (a host tuple), NOT
|
||||
|
|
@ -882,8 +875,7 @@
|
|||
(recur nxt (next ks))))
|
||||
m)))))
|
||||
|
||||
;; find-based, so nil RESULTS are cached too (the old kernel fn re-computed
|
||||
;; them); args canonicalize as a collection key.
|
||||
;; find-based, so nil RESULTS are cached too; args canonicalize as a collection key.
|
||||
(defn memoize [f]
|
||||
(let [mem (atom (hash-map))]
|
||||
(fn [& args]
|
||||
|
|
@ -920,11 +912,9 @@
|
|||
|
||||
(defn reverse [coll] (reduce conj (list) coll))
|
||||
|
||||
;; --- Phase 2 leaf batch 3 (jolt-ded) -----------------------------------------
|
||||
|
||||
;; An empty coll of the same category; sorted colls keep their comparator (the
|
||||
;; value's own :empty op). Strings and scalars are nil, as in Clojure; a lazy
|
||||
;; seq empties to () (the old kernel fn returned a host table for it).
|
||||
;; seq empties to ().
|
||||
(defn empty [coll]
|
||||
(cond
|
||||
(nil? coll) nil
|
||||
|
|
@ -948,8 +938,6 @@
|
|||
(assoc m k (apply f (get m k) args)))))]
|
||||
(up m ks f args)))
|
||||
|
||||
;; --- jolt-brh: the last missing-portable vars --------------------------------
|
||||
|
||||
;; jolt keywords have no intern table (any keyword "exists"), so find-keyword
|
||||
;; always finds — babashka makes the same call.
|
||||
(defn find-keyword
|
||||
|
|
@ -962,7 +950,7 @@
|
|||
|
||||
;; Canonical comp — here rather than a host primitive so each stage is invoked with
|
||||
;; jolt call semantics: (comp seq :content) works because the keyword stage
|
||||
;; goes through IFn dispatch (raw Janet keyword application does not).
|
||||
;; goes through IFn dispatch.
|
||||
(defn comp
|
||||
([] identity)
|
||||
([f] f)
|
||||
|
|
@ -977,17 +965,15 @@
|
|||
([x y z & args] (f (apply g x y z args)))))
|
||||
([f g & fs] (reduce comp (comp f g) fs)))
|
||||
|
||||
;; Canonical IFn set (jolt-1vx): fns, keywords, symbols, maps (sorted incl.),
|
||||
;; Canonical IFn set: fns, keywords, symbols, maps (sorted incl.),
|
||||
;; sets, vectors, and vars — NOT lists ((ifn? '(1 2)) is false in Clojure).
|
||||
;; Mutable-mode caveat: vectors and lists share the array representation
|
||||
;; there, so vector? can't separate them and lists read as ifn?.
|
||||
(defn ifn? [x]
|
||||
(or (fn? x) (keyword? x) (symbol? x) (map? x) (set? x) (vector? x) (var? x)))
|
||||
|
||||
;; Auto-promoting (') and unchecked arithmetic. Jolt numbers don't overflow,
|
||||
;; so all of these are the checked ops; fixed arities mirror Clojure's
|
||||
;; signatures. unchecked-divide-int goes through quot, so dividing by zero
|
||||
;; throws as on the JVM (the old seed fn silently truncated infinity).
|
||||
;; throws as on the JVM.
|
||||
(def +' +)
|
||||
(def -' -)
|
||||
(def *' *)
|
||||
|
|
@ -1079,7 +1065,7 @@
|
|||
(defn unchecked-float [x] (double x))
|
||||
(defn unchecked-double [x] (double x))
|
||||
|
||||
;; --- transduce / into / eduction (seed-shrink round 5) ---------------------
|
||||
;; --- transduce / into / eduction ---------------------------------------------
|
||||
;; Canonical transduce: build the stacked rf once, reduce (which honors
|
||||
;; `reduced` and steps lazy seqs incrementally), then run the completion arity.
|
||||
(defn transduce
|
||||
|
|
@ -1089,9 +1075,9 @@
|
|||
(xf (reduce xf init coll)))))
|
||||
|
||||
;; into stays a host primitive: it's perf-wall hot (the into-vec bench pays ~11%
|
||||
;; through the overlay call layers — same lesson as even?/odd? in round 4).
|
||||
;; through the overlay call layers — same lesson as even?/odd?).
|
||||
|
||||
;; eduction is EAGER on jolt (documented divergence, as before): the composed
|
||||
;; eduction is EAGER on jolt (documented divergence): the composed
|
||||
;; xforms applied to coll, realized into a vector.
|
||||
(defn eduction [& args]
|
||||
(let [coll (last args)
|
||||
|
|
@ -1102,7 +1088,7 @@
|
|||
|
||||
(defn ->Eduction [xform coll] (into [] xform coll))
|
||||
|
||||
;; --- JVM-shape stubs and trivial shells (seed-shrink batch 2) --------------
|
||||
;; --- JVM-shape stubs and trivial shells --------------------------------------
|
||||
;; Pure compositions or documented jolt stubs; the host keeps nothing.
|
||||
(defn enumeration-seq [e] (seq e))
|
||||
(defn iterator-seq [i] (seq i))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue