core: Stage 3 turn 2b — host IO, ns introspection, thread-binding family
The names turn 2a's leak removal exposed as honestly missing, now proper: - slurp/spit/flush (host-classified): path-based IO over Janet files; spit takes :append; flush flushes *out*. printf prints formatted (no newline) over the existing format. file-seq walks paths via two host dir primitives through the overlay's tree-seq. - ns-map / ns-unmap / ns-refers (ctx fns). ns-refers required fixing the refer MODEL: refer/use/:refer now map the SOURCE VAR into the target ns (the Clojure model) instead of copying its value into a new var — so source-ns redefinitions propagate, the :macro flag travels for free, and refers are identifiable by the var's home :ns. - Thread-binding family: with-bindings*/with-bindings, bound-fn*/bound-fn, bound?, thread-bound?, get-thread-bindings. The captured binding map is a Janet struct keyed by the var tables — the exact frame representation var-get reads — so it re-pushes correctly (a phm frame is invisible to var lookup). - load-string and eval interned as VALUES at the api layer (they need the loader's compile-or-interpret routing); the eval special form still handles direct calls. Suite 4532 -> 4572 (baseline floor 4540 across timeout variance, clean 86), conformance 326x3, stdlib battery, all specs+unit (+21 turn-2b rows). Coverage: missing-portable 27 -> 10 (left: the *in*-model readers, the with-local-vars/with-precision/extenders tail).
This commit is contained in:
parent
a75a26860b
commit
d61c86a068
8 changed files with 197 additions and 34 deletions
|
|
@ -151,6 +151,35 @@
|
|||
;; Clojure 1.9: true for ANY argument incl. nil (used as a spec predicate).
|
||||
(defn any? [x] true)
|
||||
|
||||
;; printf: print (no newline) the formatted string to *out*.
|
||||
(defn printf [fmt & args] (print (apply format fmt args)))
|
||||
|
||||
;; bound?: every var has a root value. (jolt vars store the root in :root;
|
||||
;; a nil-valued root reads as unbound — documented divergence.)
|
||||
(defn bound? [& vars]
|
||||
(every? (fn [v] (some? (get v :root))) vars))
|
||||
|
||||
;; Run f with a frame of dynamic bindings installed; restore on exit.
|
||||
(defn with-bindings* [binding-map f & args]
|
||||
(push-thread-bindings binding-map)
|
||||
(try
|
||||
(apply f args)
|
||||
(finally (pop-thread-bindings))))
|
||||
|
||||
;; Capture the CURRENT thread bindings; the returned fn re-installs them
|
||||
;; around every call (binding conveyance — Clojure's bound-fn*).
|
||||
(defn bound-fn* [f]
|
||||
(let [bs (get-thread-bindings)]
|
||||
(fn [& args] (apply with-bindings* bs f args))))
|
||||
|
||||
(defn thread-bound? [& vars]
|
||||
(every? (fn [v] (__thread-bound? v)) vars))
|
||||
|
||||
;; file-seq: the tree of paths under root (root included), directories walked
|
||||
;; via the host dir primitives. Paths (strings), not File objects.
|
||||
(defn file-seq [root]
|
||||
(tree-seq __dir? __list-dir root))
|
||||
|
||||
(defn comparator [pred]
|
||||
(fn [a b] (cond (pred a b) -1 (pred b a) 1 :else 0)))
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@
|
|||
[] (partition 2 bindings))]
|
||||
`(with-redefs-fn (hash-map ~@pairs) (fn [] ~@body))))
|
||||
|
||||
(defmacro with-bindings [binding-map & body]
|
||||
`(with-bindings* ~binding-map (fn [] ~@body)))
|
||||
|
||||
(defmacro bound-fn [& fntail]
|
||||
`(bound-fn* (fn ~@fntail)))
|
||||
|
||||
(defmacro defonce [name expr]
|
||||
`(let [v# (resolve (quote ~name))]
|
||||
(if (and v# (some? (var-get v#)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue