Files
rose-ash/shared/static/wasm/sx/freeze.sx
giles 5ac1ca9756 Fix server import suspension, dist sync, JIT errors
- cek_run patched to handle import suspensions via _import_hook.
  define-library (import ...) now resolves cleanly on the server.
  IO suspension errors: 190 → 0. JIT failures: ~50 → 0.
- _import_hook wired in sx_server.ml to load .sx files on demand.
- compile-modules.js syncs source .sx files to dist/sx/ before
  compiling — eliminates stale bytecode from out-of-date copies.
- WASM binary rebuilt with all fixes.
- 2658/2658 tests pass (8 new — previously failing import tests).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 22:52:41 +00:00

130 lines
3.7 KiB
Plaintext

;; ==========================================================================
;; freeze.sx — Serializable state boundaries
;;
;; Freeze scopes collect signals registered within them. On freeze,
;; their current values are serialized to SX. On thaw, values are
;; restored. Multiple named scopes can coexist independently.
;;
;; This is a library built on top of the evaluator's scoped effects
;; (scope-push!/scope-pop!/context) and signal system. It is NOT
;; part of the core evaluator — it loads after evaluator.sx.
;;
;; Usage:
;; (freeze-scope "editor"
;; (let ((doc (signal "hello")))
;; (freeze-signal "doc" doc)
;; ...))
;;
;; (cek-freeze-scope "editor") → {:name "editor" :signals {:doc "hello"}}
;; (cek-thaw-scope "editor" frozen-data) → restores signal values
;; ==========================================================================
;; Registry of freeze scopes: name → list of {name signal} entries
(define-library
(sx freeze)
(export
freeze-registry
freeze-signal
freeze-scope
cek-freeze-scope
cek-freeze-all
cek-thaw-scope
cek-thaw-all
freeze-to-sx
thaw-from-sx)
(begin
(define freeze-registry (dict))
(define
freeze-signal
:effects (mutation)
(fn
(name sig)
(let
((scope-name (context "sx-freeze-scope" nil)))
(when
scope-name
(let
((entries (or (get freeze-registry scope-name) (list))))
(append! entries (dict "name" name "signal" sig))
(dict-set! freeze-registry scope-name entries))))))
(define
freeze-scope
:effects (mutation)
(fn
(name body-fn)
(scope-push! "sx-freeze-scope" name)
(dict-set! freeze-registry name (list))
(cek-call body-fn nil)
(scope-pop! "sx-freeze-scope")
nil))
(define
cek-freeze-scope
:effects ()
(fn
(name)
(let
((entries (or (get freeze-registry name) (list)))
(signals-dict (dict)))
(for-each
(fn
(entry)
(dict-set!
signals-dict
(get entry "name")
(signal-value (get entry "signal"))))
entries)
(dict "name" name "signals" signals-dict))))
(define
cek-freeze-all
:effects ()
(fn
()
(map (fn (name) (cek-freeze-scope name)) (keys freeze-registry))))
(define
cek-thaw-scope
:effects (mutation)
(fn
(name frozen)
(let
((entries (or (get freeze-registry name) (list)))
(values (get frozen "signals")))
(when
values
(for-each
(fn
(entry)
(let
((sig-name (get entry "name"))
(sig (get entry "signal"))
(val (get values sig-name)))
(when (not (nil? val)) (reset! sig val))))
entries)))))
(define
cek-thaw-all
:effects (mutation)
(fn
(frozen-list)
(for-each
(fn (frozen) (cek-thaw-scope (get frozen "name") frozen))
frozen-list)))
(define
freeze-to-sx
:effects ()
(fn (name) (sx-serialize (cek-freeze-scope name))))
(define
thaw-from-sx
:effects (mutation)
(fn
(sx-text)
(let
((parsed (sx-parse sx-text)))
(when
(not (empty? parsed))
(let
((frozen (first parsed)))
(cek-thaw-scope (get frozen "name") frozen)))))))) ;; end define-library
;; Re-export to global namespace for backward compatibility
(import (sx freeze))