jolt/host/chez/vars.ss
Yogthos 9a21325972 refactor: registry pattern for jolt-pr-str/pr-readable + remaining arms (jolt-lmot)
The printer's two entry points (jolt-pr-str in rt.ss, jolt-pr-readable in printing.ss)
get register-pr-str-arm! / register-pr-readable-arm!, plus register-pr-arm! for the
types whose str and readable forms match (bigdec/inst/uuid/tagged/record/ns/var). The
normalize arms (sorted, lazy-seq, queue) and the uri readable arm register per-printer.
Also folds in the hash (dyn-binding var-cell), class (io uri/uuid/file), and get
(transients) arms missed earlier.

natives-array's get stays a case-lambda wrapper on purpose: its 2-arg path errors on
an out-of-bounds index while the 3-arg path returns the default, an arity distinction
the (coll k d) registry collapses — left as-is to preserve behaviour.

Completes jolt-lmot: all six dispatchers (hash/class/get/=/pr-str/pr-readable) off the
set!-rebind chains. make test green, 0 new corpus divergences; pr-str/str of inst,
uuid, bigdec, sorted-map, record-with-lazyseq, queue all verified.
2026-06-23 23:22:25 -04:00

50 lines
2.2 KiB
Scheme

;; vars as first-class objects — (var x) / #'x.
;;
;; The emitter lowers :the-var to (jolt-var ns name) — the rt.ss var-cell, which
;; is now also a Clojure VAR value. var? / var-get / deref-of-var / var-as-IFn /
;; var equality / pr-str(#'ns/name) operate on it. bound? is overridden natively
;; in post-prelude.ss (the overlay reads (get v :root), nil on a record).
;;
;; Dynamic binding (binding / with-bindings* / var-set / thread-bound? /
;; with-redefs) lives in dyn-binding.ss, which chains the var-read paths set up
;; here.
;;
;; Loaded LAST (after natives-xform.ss): chains jolt-deref (atom/volatile arms)
;; and the printers.
(define (jolt-var-pred? x) (var-cell? x))
;; the var's current root; unbound is an error (Clojure throws on an unbound var).
(define (jolt-var-get v)
(if (var-cell? v)
(let ((r (var-cell-root v)))
(if (eq? r jolt-unbound) (error #f "Unbound var" v) r))
(error #f "var-get: not a var" v)))
;; deref of a var -> its root.
(define %v-deref jolt-deref)
(set! jolt-deref (lambda (x) (if (var-cell? x) (jolt-var-get x) (%v-deref x))))
;; a var is an IFn — invoking it invokes its root value ((var f) args -> (f args)).
(define %v-invoke jolt-invoke)
(set! jolt-invoke (lambda (f . args)
(if (var-cell? f) (apply jolt-invoke (var-cell-root f) args) (apply %v-invoke f args))))
;; two var cells are = iff same ns/name (Clojure var identity).
(register-eq-arm! (lambda (a b) (or (var-cell? a) (var-cell? b)))
(lambda (a b) (and (var-cell? a) (var-cell? b)
(string=? (var-cell-ns a) (var-cell-ns b))
(string=? (var-cell-name a) (var-cell-name b)))))
;; pr-str / str of a var -> #'ns/name.
(define (var->str v) (string-append "#'" (var-cell-ns v) "/" (var-cell-name v)))
(register-pr-arm! var-cell? var->str)
(register-str-render! var-cell? var->str)
;; bound? — native (the overlay's (get v :root) is nil on a var-cell record).
(define (jolt-var-bound-one? v) (and (var-cell? v) (not (eq? (var-cell-root v) jolt-unbound))))
(define (jolt-bound? . vars) (if (for-all jolt-var-bound-one? vars) #t #f))
(def-var! "clojure.core" "var?" jolt-var-pred?)
(def-var! "clojure.core" "var-get" jolt-var-get)
(def-var! "clojure.core" "deref" jolt-deref)