Add :effects annotations to all spec files and update bootstrappers
Bootstrappers (bootstrap_py.py, js.sx) now skip :effects keyword in define forms, enabling effect annotations throughout the spec without changing generated output. Annotated 180+ functions across 14 spec files: - signals.sx: signal/deref [] pure, reset!/swap!/effect/batch [mutation] - engine.sx: parse-* [] pure, morph-*/swap-* [mutation io] - orchestration.sx: all [mutation io] (browser event binding) - adapter-html.sx: render-* [render] - adapter-dom.sx: render-* [render], reactive-* [render mutation] - adapter-sx.sx: aser-* [render] - adapter-async.sx: async-render-*/async-aser-* [render io] - parser.sx: all [] pure - render.sx: predicates [] pure, process-bindings [mutation] - boot.sx: all [mutation io] (browser init) - deps.sx: scan-*/transitive-* [] pure, compute-all-* [mutation] - router.sx: all [] pure (URL matching) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
;; render-to-dom — main entry point
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-to-dom
|
||||
(define render-to-dom :effects [render]
|
||||
(fn (expr (env :as dict) (ns :as string))
|
||||
(set-render-active! true)
|
||||
(case (type-of expr)
|
||||
@@ -66,7 +66,7 @@
|
||||
;; render-dom-list — dispatch on list head
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-dom-list
|
||||
(define render-dom-list :effects [render]
|
||||
(fn (expr (env :as dict) (ns :as string))
|
||||
(let ((head (first expr)))
|
||||
(cond
|
||||
@@ -165,7 +165,7 @@
|
||||
;; render-dom-element — create a DOM element with attrs and children
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-dom-element
|
||||
(define render-dom-element :effects [render]
|
||||
(fn ((tag :as string) (args :as list) (env :as dict) (ns :as string))
|
||||
;; Detect namespace from tag
|
||||
(let ((new-ns (cond (= tag "svg") SVG_NS
|
||||
@@ -236,7 +236,7 @@
|
||||
;; render-dom-component — expand and render a component
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-dom-component
|
||||
(define render-dom-component :effects [render]
|
||||
(fn ((comp :as component) (args :as list) (env :as dict) (ns :as string))
|
||||
;; Parse kwargs and children, bind into component env, render body.
|
||||
(let ((kwargs (dict))
|
||||
@@ -283,7 +283,7 @@
|
||||
;; render-dom-fragment — render children into a DocumentFragment
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-dom-fragment
|
||||
(define render-dom-fragment :effects [render]
|
||||
(fn ((args :as list) (env :as dict) (ns :as string))
|
||||
(let ((frag (create-fragment)))
|
||||
(for-each
|
||||
@@ -296,7 +296,7 @@
|
||||
;; render-dom-raw — insert unescaped content
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-dom-raw
|
||||
(define render-dom-raw :effects [render]
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((frag (create-fragment)))
|
||||
(for-each
|
||||
@@ -317,7 +317,7 @@
|
||||
;; render-dom-unknown-component — visible warning element
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-dom-unknown-component
|
||||
(define render-dom-unknown-component :effects [render]
|
||||
(fn ((name :as string))
|
||||
(error (str "Unknown component: " name))))
|
||||
|
||||
@@ -334,11 +334,11 @@
|
||||
"map" "map-indexed" "filter" "for-each" "portal"
|
||||
"error-boundary"))
|
||||
|
||||
(define render-dom-form?
|
||||
(define render-dom-form? :effects []
|
||||
(fn ((name :as string))
|
||||
(contains? RENDER_DOM_FORMS name)))
|
||||
|
||||
(define dispatch-render-form
|
||||
(define dispatch-render-form :effects [render]
|
||||
(fn ((name :as string) expr (env :as dict) (ns :as string))
|
||||
(cond
|
||||
;; if — reactive inside islands (re-renders when signal deps change)
|
||||
@@ -580,7 +580,7 @@
|
||||
;; render-lambda-dom — render a lambda body in DOM context
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define render-lambda-dom
|
||||
(define render-lambda-dom :effects [render]
|
||||
(fn ((f :as lambda) (args :as list) (env :as dict) (ns :as string))
|
||||
;; Bind lambda params and render body as DOM
|
||||
(let ((local (env-merge (lambda-closure f) env)))
|
||||
@@ -604,7 +604,7 @@
|
||||
;; - Attribute bindings: (deref sig) in attr → reactive attribute
|
||||
;; - Conditional fragments: (when (deref sig) ...) → reactive show/hide
|
||||
|
||||
(define render-dom-island
|
||||
(define render-dom-island :effects [render mutation]
|
||||
(fn ((island :as island) (args :as list) (env :as dict) (ns :as string))
|
||||
;; Parse kwargs and children (same as component)
|
||||
(let ((kwargs (dict))
|
||||
@@ -678,7 +678,7 @@
|
||||
;;
|
||||
;; Supports :tag keyword to change wrapper element (default "div").
|
||||
|
||||
(define render-dom-lake
|
||||
(define render-dom-lake :effects [render]
|
||||
(fn ((args :as list) (env :as dict) (ns :as string))
|
||||
(let ((lake-id nil)
|
||||
(lake-tag "div")
|
||||
@@ -722,7 +722,7 @@
|
||||
;; Renders as <div data-sx-marsh="name">children</div>.
|
||||
;; Stores the island env and transform on the element for morph retrieval.
|
||||
|
||||
(define render-dom-marsh
|
||||
(define render-dom-marsh :effects [render]
|
||||
(fn ((args :as list) (env :as dict) (ns :as string))
|
||||
(let ((marsh-id nil)
|
||||
(marsh-tag "div")
|
||||
@@ -769,7 +769,7 @@
|
||||
|
||||
;; reactive-text — create a text node bound to a signal
|
||||
;; Used when (deref sig) appears in a text position inside an island.
|
||||
(define reactive-text
|
||||
(define reactive-text :effects [render mutation]
|
||||
(fn (sig)
|
||||
(let ((node (create-text-node (str (deref sig)))))
|
||||
(effect (fn ()
|
||||
@@ -780,7 +780,7 @@
|
||||
;; Used when an attribute value contains (deref sig) inside an island.
|
||||
;; Marks the attribute name on the element via data-sx-reactive-attrs so
|
||||
;; the morph algorithm knows not to overwrite it with server content.
|
||||
(define reactive-attr
|
||||
(define reactive-attr :effects [render mutation]
|
||||
(fn (el (attr-name :as string) (compute-fn :as lambda))
|
||||
;; Mark this attribute as reactively managed
|
||||
(let ((existing (or (dom-get-attr el "data-sx-reactive-attrs") ""))
|
||||
@@ -801,7 +801,7 @@
|
||||
|
||||
;; reactive-fragment — conditionally render a fragment based on a signal
|
||||
;; Used for (when (deref sig) ...) or (if (deref sig) ...) inside an island.
|
||||
(define reactive-fragment
|
||||
(define reactive-fragment :effects [render mutation]
|
||||
(fn ((test-fn :as lambda) (render-fn :as lambda) (env :as dict) (ns :as string))
|
||||
(let ((marker (create-comment "island-fragment"))
|
||||
(current-nodes (list)))
|
||||
@@ -823,13 +823,13 @@
|
||||
;; existing DOM nodes are reused across updates. Only additions, removals,
|
||||
;; and reorderings touch the DOM. Without keys, falls back to clear+rerender.
|
||||
|
||||
(define render-list-item
|
||||
(define render-list-item :effects [render]
|
||||
(fn ((map-fn :as lambda) item (env :as dict) (ns :as string))
|
||||
(if (lambda? map-fn)
|
||||
(render-lambda-dom map-fn (list item) env ns)
|
||||
(render-to-dom (apply map-fn (list item)) env ns))))
|
||||
|
||||
(define extract-key
|
||||
(define extract-key :effects [render]
|
||||
(fn (node (index :as number))
|
||||
;; Extract key from rendered node: :key attr, data-key, or index fallback
|
||||
(let ((k (dom-get-attr node "key")))
|
||||
@@ -838,7 +838,7 @@
|
||||
(let ((dk (dom-get-data node "key")))
|
||||
(if dk (str dk) (str "__idx_" index)))))))
|
||||
|
||||
(define reactive-list
|
||||
(define reactive-list :effects [render mutation]
|
||||
(fn ((map-fn :as lambda) (items-sig :as signal) (env :as dict) (ns :as string))
|
||||
(let ((container (create-fragment))
|
||||
(marker (create-comment "island-list"))
|
||||
@@ -924,7 +924,7 @@
|
||||
;;
|
||||
;; Handles: input[text/number/email/...], textarea, select, checkbox, radio
|
||||
|
||||
(define bind-input
|
||||
(define bind-input :effects [render mutation]
|
||||
(fn (el (sig :as signal))
|
||||
(let ((input-type (lower (or (dom-get-attr el "type") "")))
|
||||
(is-checkbox (or (= input-type "checkbox")
|
||||
@@ -959,7 +959,7 @@
|
||||
;; position. Registers a disposer to clean up portal content on island
|
||||
;; teardown.
|
||||
|
||||
(define render-dom-portal
|
||||
(define render-dom-portal :effects [render]
|
||||
(fn ((args :as list) (env :as dict) (ns :as string))
|
||||
(let ((selector (trampoline (eval-expr (first args) env)))
|
||||
(target (or (dom-query selector)
|
||||
@@ -999,7 +999,7 @@
|
||||
;; (fn (err retry) ...)
|
||||
;; Calling (retry) re-renders the body, replacing the fallback.
|
||||
|
||||
(define render-dom-error-boundary
|
||||
(define render-dom-error-boundary :effects [render]
|
||||
(fn ((args :as list) (env :as dict) (ns :as string))
|
||||
(let ((fallback-expr (first args))
|
||||
(body-exprs (rest args))
|
||||
|
||||
Reference in New Issue
Block a user