Add (param :as type) annotations to all fn/lambda params across SX spec
Extend the type annotation system from defcomp-only to fn/lambda params: - Infrastructure: sf-lambda, py/js-collect-params-loop, and bootstrap_py.py now recognize (name :as type) in param lists, extracting just the name - bootstrap_py.py: add _extract_param_name() helper, fix _emit_for_each_stmt - 521 type annotations across 22 .sx spec files (eval, types, adapters, transpilers, engine, orchestration, deps, signals, router, prove, etc.) - Zero behavioral change: annotations are metadata for static analysis only - All bootstrappers (Python, JS, G1) pass, 81/81 spec tests pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
|
||||
|
||||
(define scan-refs-walk
|
||||
(fn (node refs)
|
||||
(fn (node (refs :as list))
|
||||
(cond
|
||||
;; Symbol starting with ~ → component reference
|
||||
(= (type-of node) "symbol")
|
||||
@@ -68,26 +68,26 @@
|
||||
;; that it can transitively render. Handles cycles via seen-set.
|
||||
|
||||
(define transitive-deps-walk
|
||||
(fn (n seen env)
|
||||
(fn ((n :as string) (seen :as list) (env :as dict))
|
||||
(when (not (contains? seen n))
|
||||
(append! seen n)
|
||||
(let ((val (env-get env n)))
|
||||
(cond
|
||||
(= (type-of val) "component")
|
||||
(for-each (fn (ref) (transitive-deps-walk ref seen env))
|
||||
(for-each (fn ((ref :as string)) (transitive-deps-walk ref seen env))
|
||||
(scan-refs (component-body val)))
|
||||
(= (type-of val) "macro")
|
||||
(for-each (fn (ref) (transitive-deps-walk ref seen env))
|
||||
(for-each (fn ((ref :as string)) (transitive-deps-walk ref seen env))
|
||||
(scan-refs (macro-body val)))
|
||||
:else nil)))))
|
||||
|
||||
|
||||
(define transitive-deps
|
||||
(fn (name env)
|
||||
(fn ((name :as string) (env :as dict))
|
||||
(let ((seen (list))
|
||||
(key (if (starts-with? name "~") name (str "~" name))))
|
||||
(transitive-deps-walk key seen env)
|
||||
(filter (fn (x) (not (= x key))) seen))))
|
||||
(filter (fn ((x :as string)) (not (= x key))) seen))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -101,9 +101,9 @@
|
||||
;; (component-set-deps! comp deps) → store deps on component
|
||||
|
||||
(define compute-all-deps
|
||||
(fn (env)
|
||||
(fn ((env :as dict))
|
||||
(for-each
|
||||
(fn (name)
|
||||
(fn ((name :as string))
|
||||
(let ((val (env-get env name)))
|
||||
(when (= (type-of val) "component")
|
||||
(component-set-deps! val (transitive-deps name env)))))
|
||||
@@ -120,9 +120,9 @@
|
||||
;; (regex-find-all pattern source) → list of matched group strings
|
||||
|
||||
(define scan-components-from-source
|
||||
(fn (source)
|
||||
(fn ((source :as string))
|
||||
(let ((matches (regex-find-all "\\(~([a-zA-Z_][a-zA-Z0-9_\\-]*)" source)))
|
||||
(map (fn (m) (str "~" m)) matches))))
|
||||
(map (fn ((m :as string)) (str "~" m)) matches))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -132,13 +132,13 @@
|
||||
;; the transitive closure. Returns list of ~names.
|
||||
|
||||
(define components-needed
|
||||
(fn (page-source env)
|
||||
(fn ((page-source :as string) (env :as dict))
|
||||
(let ((direct (scan-components-from-source page-source))
|
||||
(all-needed (list)))
|
||||
|
||||
;; Add each direct ref + its transitive deps
|
||||
(for-each
|
||||
(fn (name)
|
||||
(fn ((name :as string))
|
||||
(when (not (contains? all-needed name))
|
||||
(append! all-needed name))
|
||||
(let ((val (env-get env name)))
|
||||
@@ -147,7 +147,7 @@
|
||||
(component-deps val)
|
||||
(transitive-deps name env))))
|
||||
(for-each
|
||||
(fn (dep)
|
||||
(fn ((dep :as string))
|
||||
(when (not (contains? all-needed dep))
|
||||
(append! all-needed dep)))
|
||||
deps))))
|
||||
@@ -166,7 +166,7 @@
|
||||
;; This replaces the "send everything" approach with per-page bundles.
|
||||
|
||||
(define page-component-bundle
|
||||
(fn (page-source env)
|
||||
(fn ((page-source :as string) (env :as dict))
|
||||
(components-needed page-source env)))
|
||||
|
||||
|
||||
@@ -181,17 +181,17 @@
|
||||
;; (scan-css-classes source) → set/list of class strings from source
|
||||
|
||||
(define page-css-classes
|
||||
(fn (page-source env)
|
||||
(fn ((page-source :as string) (env :as dict))
|
||||
(let ((needed (components-needed page-source env))
|
||||
(classes (list)))
|
||||
|
||||
;; Collect classes from needed components
|
||||
(for-each
|
||||
(fn (name)
|
||||
(fn ((name :as string))
|
||||
(let ((val (env-get env name)))
|
||||
(when (= (type-of val) "component")
|
||||
(for-each
|
||||
(fn (cls)
|
||||
(fn ((cls :as string))
|
||||
(when (not (contains? classes cls))
|
||||
(append! classes cls)))
|
||||
(component-css-classes val)))))
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
;; Add classes from page source
|
||||
(for-each
|
||||
(fn (cls)
|
||||
(fn ((cls :as string))
|
||||
(when (not (contains? classes cls))
|
||||
(append! classes cls)))
|
||||
(scan-css-classes page-source))
|
||||
@@ -219,7 +219,7 @@
|
||||
;; (component-set-io-refs! c r) → cache IO refs on component
|
||||
|
||||
(define scan-io-refs-walk
|
||||
(fn (node io-names refs)
|
||||
(fn (node (io-names :as list) (refs :as list))
|
||||
(cond
|
||||
;; Symbol → check if name is in the IO set
|
||||
(= (type-of node) "symbol")
|
||||
@@ -242,7 +242,7 @@
|
||||
|
||||
|
||||
(define scan-io-refs
|
||||
(fn (node io-names)
|
||||
(fn (node (io-names :as list))
|
||||
(let ((refs (list)))
|
||||
(scan-io-refs-walk node io-names refs)
|
||||
refs)))
|
||||
@@ -253,7 +253,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define transitive-io-refs-walk
|
||||
(fn (n seen all-refs env io-names)
|
||||
(fn ((n :as string) (seen :as list) (all-refs :as list) (env :as dict) (io-names :as list))
|
||||
(when (not (contains? seen n))
|
||||
(append! seen n)
|
||||
(let ((val (env-get env n)))
|
||||
@@ -262,31 +262,31 @@
|
||||
(do
|
||||
;; Scan this component's body for IO refs
|
||||
(for-each
|
||||
(fn (ref)
|
||||
(fn ((ref :as string))
|
||||
(when (not (contains? all-refs ref))
|
||||
(append! all-refs ref)))
|
||||
(scan-io-refs (component-body val) io-names))
|
||||
;; Recurse into component deps
|
||||
(for-each
|
||||
(fn (dep) (transitive-io-refs-walk dep seen all-refs env io-names))
|
||||
(fn ((dep :as string)) (transitive-io-refs-walk dep seen all-refs env io-names))
|
||||
(scan-refs (component-body val))))
|
||||
|
||||
(= (type-of val) "macro")
|
||||
(do
|
||||
(for-each
|
||||
(fn (ref)
|
||||
(fn ((ref :as string))
|
||||
(when (not (contains? all-refs ref))
|
||||
(append! all-refs ref)))
|
||||
(scan-io-refs (macro-body val) io-names))
|
||||
(for-each
|
||||
(fn (dep) (transitive-io-refs-walk dep seen all-refs env io-names))
|
||||
(fn ((dep :as string)) (transitive-io-refs-walk dep seen all-refs env io-names))
|
||||
(scan-refs (macro-body val))))
|
||||
|
||||
:else nil)))))
|
||||
|
||||
|
||||
(define transitive-io-refs
|
||||
(fn (name env io-names)
|
||||
(fn ((name :as string) (env :as dict) (io-names :as list))
|
||||
(let ((all-refs (list))
|
||||
(seen (list))
|
||||
(key (if (starts-with? name "~") name (str "~" name))))
|
||||
@@ -299,9 +299,9 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define compute-all-io-refs
|
||||
(fn (env io-names)
|
||||
(fn ((env :as dict) (io-names :as list))
|
||||
(for-each
|
||||
(fn (name)
|
||||
(fn ((name :as string))
|
||||
(let ((val (env-get env name)))
|
||||
(when (= (type-of val) "component")
|
||||
(component-set-io-refs! val (transitive-io-refs name env io-names)))))
|
||||
@@ -309,7 +309,7 @@
|
||||
|
||||
|
||||
(define component-io-refs-cached
|
||||
(fn (name env io-names)
|
||||
(fn ((name :as string) (env :as dict) (io-names :as list))
|
||||
(let ((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let ((val (env-get env key)))
|
||||
(if (and (= (type-of val) "component")
|
||||
@@ -320,7 +320,7 @@
|
||||
(transitive-io-refs name env io-names))))))
|
||||
|
||||
(define component-pure?
|
||||
(fn (name env io-names)
|
||||
(fn ((name :as string) (env :as dict) (io-names :as list))
|
||||
(let ((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let ((val (env-get env key)))
|
||||
(if (and (= (type-of val) "component")
|
||||
@@ -344,7 +344,7 @@
|
||||
;; Returns: "server" | "client"
|
||||
|
||||
(define render-target
|
||||
(fn (name env io-names)
|
||||
(fn ((name :as string) (env :as dict) (io-names :as list))
|
||||
(let ((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let ((val (env-get env key)))
|
||||
(if (not (= (type-of val) "component"))
|
||||
@@ -373,7 +373,7 @@
|
||||
;; without recomputing at every request.
|
||||
|
||||
(define page-render-plan
|
||||
(fn (page-source env io-names)
|
||||
(fn ((page-source :as string) (env :as dict) (io-names :as list))
|
||||
(let ((needed (components-needed page-source env))
|
||||
(comp-targets (dict))
|
||||
(server-list (list))
|
||||
@@ -381,7 +381,7 @@
|
||||
(io-deps (list)))
|
||||
|
||||
(for-each
|
||||
(fn (name)
|
||||
(fn ((name :as string))
|
||||
(let ((target (render-target name env io-names)))
|
||||
(dict-set! comp-targets name target)
|
||||
(if (= target "server")
|
||||
@@ -389,7 +389,7 @@
|
||||
(append! server-list name)
|
||||
;; Collect IO deps from server components (use cache)
|
||||
(for-each
|
||||
(fn (io-ref)
|
||||
(fn ((io-ref :as string))
|
||||
(when (not (contains? io-deps io-ref))
|
||||
(append! io-deps io-ref)))
|
||||
(component-io-refs-cached name env io-names)))
|
||||
@@ -451,9 +451,9 @@
|
||||
;; Moved from platform to spec: pure logic using type predicates.
|
||||
|
||||
(define env-components
|
||||
(fn (env)
|
||||
(fn ((env :as dict))
|
||||
(filter
|
||||
(fn (k)
|
||||
(fn ((k :as string))
|
||||
(let ((v (env-get env k)))
|
||||
(or (component? v) (macro? v))))
|
||||
(keys env))))
|
||||
|
||||
Reference in New Issue
Block a user