Refactor phase 5d/5e: seed↔overlay registry + rep↔API boundary docs (jolt-bvek)

5d: document the seed↔overlay boundary and add a drift check. core fns split
across a Janet seed (core-X, registered in core-bindings) and a Clojure overlay;
five names (char?/sorted?/sorted-map?/sorted-set?/transduce) carry a defn in
both, with the overlay copy authoritative and the seed copy internal-only. The
into-vs-transduce home asymmetry was undocumented. Adds docs/seed-overlay-registry.md,
SEED-TWIN: comments at the five seed sites, and a build-time drift check
(test/unit/seed-overlay-registry-test.janet) that recomputes the twin set from
source and fails if it diverges or a twin leaks into core-bindings.

5e: rep↔API pointer comments in pv/plist/phm/phs/lazyseq (representation lives
here; Clojure-facing ops dispatch in core_coll/core_types) and back-pointers in
core_coll. No behavior change — comments, docs, one source-analysis test.

Full gate green (suite ≥4695 pass / ≥88 clean files), drift check passes.
This commit is contained in:
Yogthos 2026-06-15 04:22:05 -04:00
parent 6c0142e625
commit 793b55f1f3
9 changed files with 226 additions and 1 deletions

View file

@ -0,0 +1,104 @@
# Drift check for the seed ↔ overlay boundary (refactor phase 5d).
#
# Recomputes the dispatch-twin set from source and asserts it matches what
# docs/seed-overlay-registry.md documents. A twin is a name with BOTH a seed
# `core-X` defn (src/jolt/*.janet) and an overlay `(defn X …)`
# (jolt-core/clojure/core/*.clj). If you add, remove, or re-home a twin, update
# the doc table and the EXPECTED-TWINS set below together.
#
# This is source analysis, not Clojure eval — a plain Janet test (no harness).
(def repo-root
# test/unit/<this> -> repo root is two levels up
(let [d (os/cwd)] d))
(defn- slurp-safe [path]
(try (slurp path) ([_] nil)))
(defn- files-with-ext [dir ext]
(def acc @[])
(each name (os/dir dir)
(def full (string dir "/" name))
(case (os/stat full :mode)
:directory (array/concat acc (files-with-ext full ext))
:file (when (string/has-suffix? ext name) (array/push acc full))))
acc)
# Collect bare names from `(defn NAME` / `(defn- NAME`, optionally stripping a
# `prefix` (e.g. "core-") and keeping only those that had the prefix.
(defn- defn-names [src prefix]
(def names @{})
(def pat (peg/compile
~{:sym (capture (some (+ (range "az" "AZ" "09") (set "*?!<>=+/.&_-"))))
:defn (* "(defn" (? "-") (some (set " \t")) :sym)
:main (some (+ :defn 1))}))
(each m (or (peg/match pat src) @[])
(when (string? m)
(if prefix
(when (string/has-prefix? prefix m)
(put names (string/slice m (length prefix)) true))
(put names m true))))
names)
(defn- merge-into [dst src] (eachk k src (put dst k true)) dst)
# --- seed core-X names across src/jolt/*.janet ---
(def seed-names @{})
(each f (files-with-ext (string repo-root "/src/jolt") ".janet")
(merge-into seed-names (defn-names (slurp f) "core-")))
# --- overlay public defns across jolt-core/clojure/core/*.clj ---
(def overlay-names @{})
(each f (files-with-ext (string repo-root "/jolt-core/clojure/core") ".clj")
(merge-into overlay-names (defn-names (slurp f) nil)))
# --- twins = intersection ---
(def twins @{})
(eachk k seed-names (when (get overlay-names k) (put twins k true)))
(def EXPECTED-TWINS
{"char?" true "sorted?" true "sorted-map?" true "sorted-set?" true
"transduce" true})
(defn- keyset [t] (sort (keys t)))
(unless (deep= (keyset twins) (keyset EXPECTED-TWINS))
(error (string "seed↔overlay twin drift!\n"
" computed: " (string/join (keyset twins) ", ") "\n"
" expected: " (string/join (keyset EXPECTED-TWINS) ", ") "\n"
" Update docs/seed-overlay-registry.md and EXPECTED-TWINS together.")))
# --- core-bindings registered keys (the public/dispatch registration table) ---
(def core-src (slurp (string repo-root "/src/jolt/core.janet")))
(def bind-start (string/find "@{" core-src (string/find "core-bindings" core-src)))
# brace-match from the `@{` to its close
(defn- match-brace [src open]
(var depth 0) (var i open) (var end nil)
(while (and (< i (length src)) (nil? end))
(case (src i)
(chr "{") (++ depth)
(chr "}") (do (-- depth) (when (= depth 0) (set end i))))
(++ i))
end)
(def bind-end (match-brace core-src (+ bind-start 1)))
(def bind-region (string/slice core-src bind-start (+ bind-end 1)))
(def registered @{})
(each m (or (peg/match ~(some (+ (* "\"" (capture (some (if-not "\"" 1))) "\"") 1)) bind-region) @[])
(put registered m true))
# Twins must NOT be registered — the overlay copy shadows; the seed copy is
# internal-only. A twin sneaking into core-bindings means the seed copy is
# masquerading as the public binding.
(eachk t EXPECTED-TWINS
(when (get registered t)
(error (string "twin '" t "' is registered in core-bindings — it should be "
"overlay-public only (see docs/seed-overlay-registry.md)"))))
# The seed-public anchors must stay registered (guards the into/transduce
# asymmetry the registry documents).
(each anchor ["into" "reduce"]
(unless (get registered anchor)
(error (string "seed-public anchor '" anchor "' missing from core-bindings"))))
(print "seed↔overlay registry: " (length (keys twins)) " twins, "
(length (keys registered)) " registered bindings — OK")