Chez parity: delay / force / realized? (jolt-cf1q.7)

Add a thread-safe delay type (concurrency.ss): make-delay wraps a thunk; deref/
force run it once under a lock and cache (JVM delays are thread-safe + memoized).
delay? and realized?-on-a-delay are native; the overlay's `delay` macro
(-> make-delay) and `force` (-> deref) now work. realized? wrapper (post-prelude)
and the deref chain gain a delay arm. Removed the np-delay? stub from
natives-parity.ss (the real type lives in concurrency.ss).

Seed unchanged (no re-mint). zero-Janet 2673->2685, 0 new divergences; Janet gate
+ JVM cert green.

jolt-cf1q.7
This commit is contained in:
Yogthos 2026-06-20 17:02:42 -04:00
parent 4b4d677fe4
commit 1d6e740668
4 changed files with 26 additions and 11 deletions

View file

@ -214,9 +214,23 @@
(jolt-agent-state-set! a new-state)
a)
;; --- delay (lazy once-forced computation) -----------------------------------
;; (delay body) -> (make-delay (fn [] body)) (overlay macro); force/deref run the
;; thunk once under a lock and cache the value (JVM delays are thread-safe). force
;; (overlay) is (if (delay? x) (deref x) x), so it works once delay?/deref do.
(define-record-type jolt-delay (fields thunk (mutable realized?) (mutable value) mu)
(nongenerative jolt-delay-v1))
(define (jolt-make-delay thunk) (make-jolt-delay thunk #f jolt-nil (make-mutex)))
(define (jolt-delay-force d)
(with-mutex (jolt-delay-mu d)
(unless (jolt-delay-realized? d)
(jolt-delay-value-set! d (jolt-invoke (jolt-delay-thunk d)))
(jolt-delay-realized?-set! d #t)))
(jolt-delay-value d))
;; --- deref extension --------------------------------------------------------
;; Chain the fully-built jolt-deref (atoms/vars/volatiles/reduced) with futures,
;; promises, and agents, and accept the timed (deref ref ms val) arity for the
;; promises, agents, and delays; accept the timed (deref ref ms val) arity for the
;; blocking ref types.
(define %pre-conc-deref jolt-deref)
(set! jolt-deref
@ -229,13 +243,15 @@
(if (null? opts) (jolt-promise-deref x)
(jolt-promise-deref-timed x (car opts) (cadr opts))))
((jolt-agent? x) (jolt-agent-state x))
((jolt-delay? x) (jolt-delay-force x))
(else (apply %pre-conc-deref x opts)))))
;; realized? for a Chez future/promise (the overlay reads Janet map keys). Wrap the
;; overlay version in post-prelude.ss; here just the future/promise predicate.
;; realized? for a Chez future/promise/delay (the overlay reads Janet map keys).
;; Wrapped over the overlay version in post-prelude.ss.
(define (jolt-conc-realized? x)
(cond ((jolt-future? x) (jolt-future-done? x))
((jolt-promise? x) (jolt-promise-delivered? x))
((jolt-delay? x) (jolt-delay-realized? x))
(else #f)))
;; --- bind into clojure.core -------------------------------------------------
@ -253,4 +269,6 @@
(def-var! "clojure.core" "await" jolt-agent-await)
(def-var! "clojure.core" "agent-error" jolt-agent-error)
(def-var! "clojure.core" "restart-agent" jolt-agent-restart)
(def-var! "clojure.core" "make-delay" jolt-make-delay)
(def-var! "clojure.core" "delay?" jolt-delay?)
(def-var! "clojure.core" "deref" jolt-deref)

View file

@ -62,9 +62,7 @@
(define (np-re-matcher re s)
(jolt-hash-map np-kw-type np-kw-mat np-kw-re re np-kw-s s np-kw-pos 0.0))
;; --- delay? : no delay type is built on Chez yet, so always false (enough for
;; (delay? x) on non-delays; revisit when delay/force land).
(define (np-delay? x) #f)
;; (delay? / make-delay / force live in concurrency.ss with the real delay type.)
;; --- macroexpand-1 / macroexpand: expand a (quoted) call form via the runtime
;; macro table (host-contract hc-macro?/hc-expand-1; forward-referenced, resolved
@ -90,6 +88,5 @@
(def-var! "clojure.core" "__reader-features-set!" np-reader-features-set!)
(def-var! "clojure.core" "reader-conditional" np-reader-conditional)
(def-var! "clojure.core" "re-matcher" np-re-matcher)
(def-var! "clojure.core" "delay?" np-delay?)
(def-var! "clojure.core" "macroexpand-1" np-macroexpand-1)
(def-var! "clojure.core" "macroexpand" np-macroexpand)

View file

@ -62,6 +62,6 @@
(let ((overlay-realized? (var-deref "clojure.core" "realized?")))
(def-var! "clojure.core" "realized?"
(lambda (x)
(if (or (jolt-future? x) (jolt-promise? x))
(if (or (jolt-future? x) (jolt-promise? x) (jolt-delay? x))
(jolt-conc-realized? x)
(jolt-invoke overlay-realized? x)))))