Implement deref-as-shift: ReactiveResetFrame, DerefFrame, continuation capture

frames.sx: ReactiveResetFrame + DerefFrame constructors,
kont-capture-to-reactive-reset, has-reactive-reset-frame?.
cek.sx: deref as CEK special form, step-sf-deref pushes DerefFrame,
reactive-shift-deref captures continuation as signal subscriber,
ReactiveResetFrame in step-continue calls update-fn on re-render.
adapter-dom.sx: cek-reactive-text/cek-reactive-attr using cek-run
with ReactiveResetFrame for implicit DOM bindings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 01:13:21 +00:00
parent 90febbd91e
commit 5c4a8c8cc2
3 changed files with 161 additions and 1 deletions

View File

@@ -1107,6 +1107,48 @@
(reset! sig (dom-get-prop el "value"))))))))
;; --------------------------------------------------------------------------
;; CEK-based reactive rendering (opt-in, deref-as-shift)
;; --------------------------------------------------------------------------
;;
;; When enabled, (deref sig) inside a reactive-reset boundary performs
;; continuation capture: "the rest of this expression" becomes the subscriber.
;; No explicit effect() wrapping needed for text/attr bindings.
(define *use-cek-reactive* true)
(define enable-cek-reactive! (fn () (set! *use-cek-reactive* true)))
;; cek-reactive-text — create a text node bound via continuation capture
(define cek-reactive-text :effects [render mutation]
(fn (expr env)
(let ((node (create-text-node ""))
(update-fn (fn (val)
(dom-set-text-content node (str val)))))
(let ((initial (cek-run
(make-cek-state expr env
(list (make-reactive-reset-frame env update-fn true))))))
(dom-set-text-content node (str initial))
node))))
;; cek-reactive-attr — bind an attribute via continuation capture
(define cek-reactive-attr :effects [render mutation]
(fn (el attr-name expr env)
(let ((update-fn (fn (val)
(cond
(or (nil? val) (= val false)) (dom-remove-attr el attr-name)
(= val true) (dom-set-attr el attr-name "")
:else (dom-set-attr el attr-name (str val))))))
;; Mark for morph protection
(let ((existing (or (dom-get-attr el "data-sx-reactive-attrs") ""))
(updated (if (empty? existing) attr-name (str existing "," attr-name))))
(dom-set-attr el "data-sx-reactive-attrs" updated))
;; Initial render via CEK with ReactiveResetFrame
(let ((initial (cek-run
(make-cek-state expr env
(list (make-reactive-reset-frame env update-fn true))))))
(invoke update-fn initial)))))
;; --------------------------------------------------------------------------
;; render-dom-portal — render children into a remote target element
;; --------------------------------------------------------------------------