The dominant prelude-parity crash bucket was 'apply non-procedure jolt-nil': core fns calling seed-native seq fns (core_coll.janet) that have no Chez RT shim, so var-deref returns jolt-nil. A static scan of the assembled prelude turned up 52 referenced-but-undefined clojure.core names. host/chez/natives-seq.ss shims the safe seq fns over the existing seq layer: mapcat, take-while, drop-while, partition (collection arities only — the 1-arg transducer forms are jolt-kxsr), and sort (compare default; a comparator may return a 3-way number or a boolean less-than). reduced/reduced? is a jolt-reduced record in seq.ss that reduce short-circuits on and deref unwraps, so unreduced works. identical? = jolt= (the seed's definition). Deferred list?: a Chez lazy seq and a list are both cseq, so it can't be told apart without a distinct list type — a real divergence risk. Parity 1407 -> 1467/2497, 0 new divergences. emit-test 263/263.
60 lines
2.5 KiB
Scheme
60 lines
2.5 KiB
Scheme
;; atoms (jolt-9ziu) — host-coupled mutable reference cells for the Chez host.
|
|
;;
|
|
;; atom/deref/swap!/reset! stay in the Janet seed (not the clojure.core overlay),
|
|
;; so the Chez runtime needs native shims, def-var!'d into clojure.core. They
|
|
;; lower to var-deref in prelude mode. The hierarchy machinery
|
|
;; (global-hierarchy = (atom (make-hierarchy))) calls `atom` at the prelude's
|
|
;; LOAD time, so without this shim the whole prelude fails to load.
|
|
;;
|
|
;; compare-and-set!/swap-vals!/reset-vals! are overlay fns over the native kernel
|
|
;; in the live system; provided here natively too so the Chez host is
|
|
;; self-sufficient for atoms without the full prelude (the overlay versions, when
|
|
;; the full prelude loads, override these but compose the same native kernel).
|
|
|
|
(define-record-type jolt-atom (fields (mutable val)) (nongenerative jolt-atom-v1))
|
|
|
|
;; (atom init) — extra :meta/:validator opts are accepted and ignored for now
|
|
;; (watches/validators are overlay features layered via jolt.host/ref-put!).
|
|
(define (jolt-atom-new v . _opts) (make-jolt-atom v))
|
|
|
|
;; deref reads an atom; it also unwraps a `reduced` (Clojure @(reduced x) => x,
|
|
;; which the overlay's `unreduced` relies on). The reduced record is in seq.ss.
|
|
(define (jolt-deref x)
|
|
(cond
|
|
((jolt-atom? x) (jolt-atom-val x))
|
|
((jolt-reduced? x) (jolt-reduced-val x))
|
|
(else (error #f "deref: unsupported reference type" x))))
|
|
|
|
;; (swap! a f arg*) -> (reset! a (f @a arg*)); f is invoked through jolt-invoke
|
|
;; (a jolt fn value, keyword, or invokable collection).
|
|
(define (jolt-swap! a f . args)
|
|
(let ((nv (apply jolt-invoke f (jolt-atom-val a) args)))
|
|
(jolt-atom-val-set! a nv)
|
|
nv))
|
|
|
|
(define (jolt-reset! a v) (jolt-atom-val-set! a v) v)
|
|
|
|
(define (jolt-compare-and-set! a oldv newv)
|
|
(if (jolt= (jolt-atom-val a) oldv)
|
|
(begin (jolt-atom-val-set! a newv) #t)
|
|
#f))
|
|
|
|
(define (jolt-swap-vals! a f . args)
|
|
(let* ((old (jolt-atom-val a))
|
|
(nv (apply jolt-invoke f old args)))
|
|
(jolt-atom-val-set! a nv)
|
|
(jolt-vector old nv)))
|
|
|
|
(define (jolt-reset-vals! a v)
|
|
(let ((old (jolt-atom-val a)))
|
|
(jolt-atom-val-set! a v)
|
|
(jolt-vector old v)))
|
|
|
|
(def-var! "clojure.core" "atom" jolt-atom-new)
|
|
(def-var! "clojure.core" "deref" jolt-deref)
|
|
(def-var! "clojure.core" "swap!" jolt-swap!)
|
|
(def-var! "clojure.core" "reset!" jolt-reset!)
|
|
(def-var! "clojure.core" "compare-and-set!" jolt-compare-and-set!)
|
|
(def-var! "clojure.core" "swap-vals!" jolt-swap-vals!)
|
|
(def-var! "clojure.core" "reset-vals!" jolt-reset-vals!)
|
|
(def-var! "clojure.core" "atom?" jolt-atom?)
|