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
69
stdlib/clojure/edn.clj
Normal file
69
stdlib/clojure/edn.clj
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
;; clojure.edn — reading EDN data. Delegates to the Jolt reader via
|
||||
;; clojure.core/read-string (which parses, never evaluates — safe for EDN), and
|
||||
;; adds the opts-map arity with :eof plus nil/blank-input handling.
|
||||
(ns clojure.edn
|
||||
"Reading EDN data."
|
||||
(:require [clojure.string :as cstr]))
|
||||
|
||||
;; The reader yields set literals as a FORM ({:jolt/type :jolt/set :value [...]})
|
||||
;; rather than a constructed set, so build the actual values, recursing into
|
||||
;; maps/vectors/lists. (Lists stay lists — EDN never evaluates them as code.)
|
||||
(defn- edn->value [opts x]
|
||||
(cond
|
||||
;; Reader FORMS are detected by :jolt/type tag, never by map? — strict map?
|
||||
;; (correctly) excludes tagged structs, so the old (and (map? x) ...) guard
|
||||
;; would skip them.
|
||||
(= :jolt/set (get x :jolt/type)) (set (map (fn [v] (edn->value opts v)) (get x :value)))
|
||||
;; Tagged elements: a reader from the :readers opt wins, then the built-in
|
||||
;; data readers (#uuid/#inst + registered); an unknown tag falls to the
|
||||
;; :default opt fn (called with tag and value, as in Clojure) or throws.
|
||||
(= :jolt/tagged (get x :jolt/type))
|
||||
(let [tag (get x :tag)
|
||||
v (edn->value opts (get x :form))
|
||||
;; the reader stores the tag as a :#name keyword; :readers maps are
|
||||
;; keyed by the SYMBOL (Clojure's shape) — normalize for lookup
|
||||
tag-sym (let [n (name tag)]
|
||||
(symbol (if (= "#" (subs n 0 1)) (subs n 1) n)))
|
||||
custom (get (get opts :readers) tag-sym)]
|
||||
(cond
|
||||
custom (custom v)
|
||||
(get opts :default) ((get opts :default) tag v)
|
||||
:else (__read-tagged tag v)))
|
||||
(map? x)
|
||||
(into {} (map (fn [e] [(edn->value opts (key e)) (edn->value opts (val e))]) x))
|
||||
(vector? x) (mapv (fn [v] (edn->value opts v)) x)
|
||||
(seq? x) (map (fn [v] (edn->value opts v)) x)
|
||||
:else x))
|
||||
|
||||
;; Private helper, NOT named read-string: an unqualified (read-string …) call
|
||||
;; dispatches the core read-string SPECIAL FORM (by name, regardless of ns), so
|
||||
;; the 1-arity can't delegate to the 2-arity through that name.
|
||||
(defn- read-edn [opts s]
|
||||
(if (or (nil? s) (cstr/blank? s))
|
||||
(get opts :eof nil)
|
||||
(edn->value opts (clojure.core/read-string s))))
|
||||
|
||||
(defn read-string
|
||||
"Reads one object from the string s. Returns the :eof option value (default
|
||||
nil) for nil or blank input. opts is an options map; :eof sets the value
|
||||
returned at end of input."
|
||||
([s] (read-edn {} s))
|
||||
([opts s] (read-edn opts s)))
|
||||
|
||||
(defn- drain-reader
|
||||
"All remaining content of a reader as a string. Shim readers (StringReader,
|
||||
PushbackReader, io/reader results) expose char-wise .read; a raw file
|
||||
handle is read whole."
|
||||
[reader]
|
||||
(if (= :core/file (janet/type reader))
|
||||
(janet.file/read reader :all)
|
||||
(loop [acc (transient []) c (.read reader)]
|
||||
(if (== -1 c)
|
||||
(apply str (map char (persistent! acc)))
|
||||
(recur (conj! acc c) (.read reader))))))
|
||||
|
||||
(defn read
|
||||
"Reads one EDN object from reader (a PushbackReader or any jolt reader).
|
||||
Returns the :eof option value (default nil) at end of input."
|
||||
([reader] (read {} reader))
|
||||
([opts reader] (read-edn opts (drain-reader reader))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue