Bytecode compiler: desugar let-match, fix SPA navigation
The bytecode compiler now handles let-match (both variants):
- Variant 1: (let-match name expr {:k v} body...) — named binding + destructure
- Variant 2: (let-match {:k v} expr body...) — pattern-only destructure
Desugars to sequential let + get calls — no new opcodes needed.
This was the last blocker for SPA navigation. The bytecoded orchestration
and router modules used let-match which compiled to CALL_PRIM "let-match"
(undefined at runtime). Now desugared at compile time.
Also synced dist/sx/ sources with web/ and recompiled all 26 .sxbc modules.
2650/2650 tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
compile-or
|
||||
compile-begin
|
||||
compile-let
|
||||
desugar-let-match
|
||||
compile-letrec
|
||||
compile-lambda
|
||||
compile-define
|
||||
@@ -250,6 +251,8 @@
|
||||
(compile-let em args scope tail?)
|
||||
(= name "let*")
|
||||
(compile-let em args scope tail?)
|
||||
(= name "let-match")
|
||||
(compile-let em (desugar-let-match args) scope tail?)
|
||||
(= name "begin")
|
||||
(compile-begin em args scope tail?)
|
||||
(= name "do")
|
||||
@@ -446,6 +449,47 @@
|
||||
(compile-expr em (first exprs) scope false)
|
||||
(emit-op em 5)
|
||||
(compile-begin em (rest exprs) scope tail?))))))
|
||||
(define
|
||||
desugar-let-match
|
||||
(fn
|
||||
(args)
|
||||
(let
|
||||
((first-arg (first args)))
|
||||
(if (dict? first-arg)
|
||||
;; Variant 2: (let-match {:k v} expr body...)
|
||||
(let
|
||||
((pattern first-arg)
|
||||
(expr (nth args 1))
|
||||
(body (slice args 2))
|
||||
(src-sym (make-symbol "__lm_tmp"))
|
||||
(bindings (list)))
|
||||
(append! bindings (list src-sym expr))
|
||||
(for-each
|
||||
(fn (k)
|
||||
(append! bindings
|
||||
(list (get pattern k)
|
||||
(list (make-symbol "get") src-sym (str k)))))
|
||||
(keys pattern))
|
||||
(cons bindings body))
|
||||
;; Variant 1: (let-match name expr {:k v} body...)
|
||||
(let
|
||||
((name-sym first-arg)
|
||||
(expr (nth args 1))
|
||||
(pattern (nth args 2))
|
||||
(body (slice args 3))
|
||||
(src-sym (if (= (str name-sym) "_")
|
||||
(make-symbol "__lm_tmp")
|
||||
name-sym))
|
||||
(bindings (list)))
|
||||
(append! bindings (list src-sym expr))
|
||||
(when (dict? pattern)
|
||||
(for-each
|
||||
(fn (k)
|
||||
(append! bindings
|
||||
(list (get pattern k)
|
||||
(list (make-symbol "get") src-sym (str k)))))
|
||||
(keys pattern)))
|
||||
(cons bindings body))))))
|
||||
(define
|
||||
compile-let
|
||||
(fn
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
|
||||
|
||||
(define-library (web deps)
|
||||
(define-library
|
||||
(web deps)
|
||||
(export
|
||||
scan-refs
|
||||
scan-refs-walk
|
||||
@@ -22,347 +23,351 @@
|
||||
page-render-plan
|
||||
env-components)
|
||||
(begin
|
||||
|
||||
(define
|
||||
scan-refs
|
||||
:effects ()
|
||||
(fn (node) (let ((refs (list))) (scan-refs-walk node refs) refs)))
|
||||
|
||||
(define
|
||||
scan-refs-walk
|
||||
:effects ()
|
||||
(fn
|
||||
(node (refs :as list))
|
||||
(cond
|
||||
(= (type-of node) "symbol")
|
||||
(let
|
||||
((name (symbol-name node)))
|
||||
(when
|
||||
(starts-with? name "~")
|
||||
(when (not (contains? refs name)) (append! refs name))))
|
||||
(= (type-of node) "list")
|
||||
(for-each (fn (item) (scan-refs-walk item refs)) node)
|
||||
(= (type-of node) "dict")
|
||||
(for-each
|
||||
(fn (key) (scan-refs-walk (dict-get node key) refs))
|
||||
(keys node))
|
||||
:else nil)))
|
||||
|
||||
(define
|
||||
transitive-deps-walk
|
||||
:effects ()
|
||||
(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
|
||||
(or (= (type-of val) "component") (= (type-of val) "island"))
|
||||
(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 :as string)) (transitive-deps-walk ref seen env))
|
||||
(scan-refs (macro-body val)))
|
||||
:else nil)))))
|
||||
|
||||
(define
|
||||
transitive-deps
|
||||
:effects ()
|
||||
(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 :as string)) (not (= x key))) seen))))
|
||||
|
||||
(define
|
||||
compute-all-deps
|
||||
:effects (mutation)
|
||||
(fn
|
||||
((env :as dict))
|
||||
(for-each
|
||||
(define
|
||||
scan-refs
|
||||
:effects ()
|
||||
(fn (node) (let ((refs (list))) (scan-refs-walk node refs) refs)))
|
||||
(define
|
||||
scan-refs-walk
|
||||
:effects ()
|
||||
(fn
|
||||
((name :as string))
|
||||
(let
|
||||
((val (env-get env name)))
|
||||
(when
|
||||
(or (= (type-of val) "component") (= (type-of val) "island"))
|
||||
(component-set-deps! val (transitive-deps name env)))))
|
||||
(env-components env))))
|
||||
|
||||
(define
|
||||
scan-components-from-source
|
||||
:effects ()
|
||||
(fn
|
||||
((source :as string))
|
||||
(let
|
||||
((matches (regex-find-all "\\(~([a-zA-Z_][a-zA-Z0-9_\\-:/]*)" source)))
|
||||
(map (fn ((m :as string)) (str "~" m)) matches))))
|
||||
|
||||
(define
|
||||
components-needed
|
||||
:effects ()
|
||||
(fn
|
||||
((page-source :as string) (env :as dict))
|
||||
(let
|
||||
((direct (scan-components-from-source page-source))
|
||||
(all-needed (list)))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(when (not (contains? all-needed name)) (append! all-needed name))
|
||||
(let
|
||||
((val (env-get env name)))
|
||||
(node (refs :as list))
|
||||
(match
|
||||
(type-of node)
|
||||
("symbol"
|
||||
(let
|
||||
((deps (if (and (= (type-of val) "component") (not (empty? (component-deps val)))) (component-deps val) (transitive-deps name env))))
|
||||
(for-each
|
||||
(fn
|
||||
((dep :as string))
|
||||
(when
|
||||
(not (contains? all-needed dep))
|
||||
(append! all-needed dep)))
|
||||
deps))))
|
||||
direct)
|
||||
all-needed)))
|
||||
|
||||
(define
|
||||
page-component-bundle
|
||||
:effects ()
|
||||
(fn
|
||||
((page-source :as string) (env :as dict))
|
||||
(components-needed page-source env)))
|
||||
|
||||
(define
|
||||
page-css-classes
|
||||
:effects ()
|
||||
(fn
|
||||
((page-source :as string) (env :as dict))
|
||||
(let
|
||||
((needed (components-needed page-source env)) (classes (list)))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(let
|
||||
((val (env-get env name)))
|
||||
(when
|
||||
(= (type-of val) "component")
|
||||
(for-each
|
||||
(fn
|
||||
((cls :as string))
|
||||
(when (not (contains? classes cls)) (append! classes cls)))
|
||||
(component-css-classes val)))))
|
||||
needed)
|
||||
(for-each
|
||||
(fn
|
||||
((cls :as string))
|
||||
(when (not (contains? classes cls)) (append! classes cls)))
|
||||
(scan-css-classes page-source))
|
||||
classes)))
|
||||
|
||||
(define
|
||||
scan-io-refs-walk
|
||||
:effects ()
|
||||
(fn
|
||||
(node (io-names :as list) (refs :as list))
|
||||
(cond
|
||||
(= (type-of node) "symbol")
|
||||
(let
|
||||
((name (symbol-name node)))
|
||||
(when
|
||||
(contains? io-names name)
|
||||
(when (not (contains? refs name)) (append! refs name))))
|
||||
(= (type-of node) "list")
|
||||
(for-each (fn (item) (scan-io-refs-walk item io-names refs)) node)
|
||||
(= (type-of node) "dict")
|
||||
(for-each
|
||||
(fn (key) (scan-io-refs-walk (dict-get node key) io-names refs))
|
||||
(keys node))
|
||||
:else nil)))
|
||||
|
||||
(define
|
||||
scan-io-refs
|
||||
:effects ()
|
||||
(fn
|
||||
(node (io-names :as list))
|
||||
(let ((refs (list))) (scan-io-refs-walk node io-names refs) refs)))
|
||||
|
||||
(define
|
||||
transitive-io-refs-walk
|
||||
:effects ()
|
||||
(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)))
|
||||
(cond
|
||||
(= (type-of val) "component")
|
||||
(do
|
||||
((name (symbol-name node)))
|
||||
(when
|
||||
(starts-with? name "~")
|
||||
(when (not (contains? refs name)) (append! refs name)))))
|
||||
("list" (for-each (fn (item) (scan-refs-walk item refs)) node))
|
||||
("dict"
|
||||
(for-each
|
||||
(fn
|
||||
((ref :as string))
|
||||
(when (not (contains? all-refs ref)) (append! all-refs ref)))
|
||||
(scan-io-refs (component-body val) io-names))
|
||||
(for-each
|
||||
(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 :as string))
|
||||
(when (not (contains? all-refs ref)) (append! all-refs ref)))
|
||||
(scan-io-refs (macro-body val) io-names))
|
||||
(for-each
|
||||
(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
|
||||
:effects ()
|
||||
(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))))
|
||||
(transitive-io-refs-walk key seen all-refs env io-names)
|
||||
all-refs)))
|
||||
|
||||
(define
|
||||
compute-all-io-refs
|
||||
:effects (mutation)
|
||||
(fn
|
||||
((env :as dict) (io-names :as list))
|
||||
(for-each
|
||||
(fn (key) (scan-refs-walk (dict-get node key) refs))
|
||||
(keys node)))
|
||||
(_ nil))))
|
||||
(define
|
||||
transitive-deps-walk
|
||||
:effects ()
|
||||
(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)))))
|
||||
(env-components env))))
|
||||
|
||||
(define
|
||||
component-io-refs-cached
|
||||
:effects ()
|
||||
(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")
|
||||
(not (nil? (component-io-refs val)))
|
||||
(not (empty? (component-io-refs val))))
|
||||
(component-io-refs val)
|
||||
(transitive-io-refs name env io-names))))))
|
||||
|
||||
(define
|
||||
component-pure?
|
||||
:effects ()
|
||||
(fn
|
||||
(name (env :as dict) (io-names :as list))
|
||||
(let
|
||||
((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let
|
||||
((val (if (env-has? env key) (env-get env key) nil)))
|
||||
(if
|
||||
(and
|
||||
(= (type-of val) "component")
|
||||
(not (nil? (component-io-refs val)))
|
||||
(not (empty? (component-io-refs val))))
|
||||
false
|
||||
(empty? (transitive-io-refs name env io-names)))))))
|
||||
|
||||
(define
|
||||
render-target
|
||||
:effects ()
|
||||
(fn
|
||||
(name (env :as dict) (io-names :as list))
|
||||
(let
|
||||
((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let
|
||||
((val (if (env-has? env key) (env-get env key) nil)))
|
||||
(if
|
||||
(not (= (type-of val) "component"))
|
||||
"server"
|
||||
((n :as string) (seen :as list) (env :as dict))
|
||||
(when
|
||||
(not (contains? seen n))
|
||||
(append! seen n)
|
||||
(let
|
||||
((affinity (component-affinity val)))
|
||||
(cond
|
||||
(= affinity "server")
|
||||
"server"
|
||||
(= affinity "client")
|
||||
"client"
|
||||
(not (component-pure? name env io-names))
|
||||
"server"
|
||||
:else "client")))))))
|
||||
|
||||
(define
|
||||
page-render-plan
|
||||
:effects ()
|
||||
(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))
|
||||
(client-list (list))
|
||||
(io-deps (list)))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(let
|
||||
((target (render-target name env io-names)))
|
||||
(dict-set! comp-targets name target)
|
||||
(if
|
||||
(= target "server")
|
||||
(do
|
||||
(append! server-list name)
|
||||
((val (env-get env n)))
|
||||
(match
|
||||
(type-of val)
|
||||
("component"
|
||||
(for-each
|
||||
(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)))
|
||||
(append! client-list name))))
|
||||
needed)
|
||||
{:io-deps io-deps :server server-list :components comp-targets :client client-list})))
|
||||
|
||||
(define
|
||||
env-components
|
||||
:effects ()
|
||||
(fn
|
||||
((env :as dict))
|
||||
(filter
|
||||
((ref :as string))
|
||||
(transitive-deps-walk ref seen env))
|
||||
(scan-refs (component-body val))))
|
||||
("island"
|
||||
(for-each
|
||||
(fn
|
||||
((ref :as string))
|
||||
(transitive-deps-walk ref seen env))
|
||||
(scan-refs (component-body val))))
|
||||
("macro"
|
||||
(for-each
|
||||
(fn
|
||||
((ref :as string))
|
||||
(transitive-deps-walk ref seen env))
|
||||
(scan-refs (macro-body val))))
|
||||
(_ nil))))))
|
||||
(define
|
||||
transitive-deps
|
||||
:effects ()
|
||||
(fn
|
||||
((k :as string))
|
||||
(let ((v (env-get env k))) (or (component? v) (macro? v))))
|
||||
(keys env))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
((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 :as string)) (not (= x key))) seen))))
|
||||
(define
|
||||
compute-all-deps
|
||||
:effects (mutation)
|
||||
(fn
|
||||
((env :as dict))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(let
|
||||
((val (env-get env name)))
|
||||
(when
|
||||
(or
|
||||
(= (type-of val) "component")
|
||||
(= (type-of val) "island"))
|
||||
(component-set-deps! val (transitive-deps name env)))))
|
||||
(env-components env))))
|
||||
(define
|
||||
scan-components-from-source
|
||||
:effects ()
|
||||
(fn
|
||||
((source :as string))
|
||||
(let
|
||||
((matches (regex-find-all "\\(~([a-zA-Z_][a-zA-Z0-9_\\-:/]*)" source)))
|
||||
(map (fn ((m :as string)) (str "~" m)) matches))))
|
||||
(define
|
||||
components-needed
|
||||
:effects ()
|
||||
(fn
|
||||
((page-source :as string) (env :as dict))
|
||||
(let
|
||||
((direct (scan-components-from-source page-source))
|
||||
(all-needed (list)))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(when
|
||||
(not (contains? all-needed name))
|
||||
(append! all-needed name))
|
||||
(let
|
||||
((val (env-get env name)))
|
||||
(let
|
||||
((deps (if (and (= (type-of val) "component") (not (empty? (component-deps val)))) (component-deps val) (transitive-deps name env))))
|
||||
(for-each
|
||||
(fn
|
||||
((dep :as string))
|
||||
(when
|
||||
(not (contains? all-needed dep))
|
||||
(append! all-needed dep)))
|
||||
deps))))
|
||||
direct)
|
||||
all-needed)))
|
||||
(define
|
||||
page-component-bundle
|
||||
:effects ()
|
||||
(fn
|
||||
((page-source :as string) (env :as dict))
|
||||
(components-needed page-source env)))
|
||||
(define
|
||||
page-css-classes
|
||||
:effects ()
|
||||
(fn
|
||||
((page-source :as string) (env :as dict))
|
||||
(let
|
||||
((needed (components-needed page-source env)) (classes (list)))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(let
|
||||
((val (env-get env name)))
|
||||
(when
|
||||
(= (type-of val) "component")
|
||||
(for-each
|
||||
(fn
|
||||
((cls :as string))
|
||||
(when
|
||||
(not (contains? classes cls))
|
||||
(append! classes cls)))
|
||||
(component-css-classes val)))))
|
||||
needed)
|
||||
(for-each
|
||||
(fn
|
||||
((cls :as string))
|
||||
(when (not (contains? classes cls)) (append! classes cls)))
|
||||
(scan-css-classes page-source))
|
||||
classes)))
|
||||
(define
|
||||
scan-io-refs-walk
|
||||
:effects ()
|
||||
(fn
|
||||
(node (io-names :as list) (refs :as list))
|
||||
(match
|
||||
(type-of node)
|
||||
("symbol"
|
||||
(let
|
||||
((name (symbol-name node)))
|
||||
(when
|
||||
(contains? io-names name)
|
||||
(when (not (contains? refs name)) (append! refs name)))))
|
||||
("list"
|
||||
(for-each
|
||||
(fn (item) (scan-io-refs-walk item io-names refs))
|
||||
node))
|
||||
("dict"
|
||||
(for-each
|
||||
(fn
|
||||
(key)
|
||||
(scan-io-refs-walk (dict-get node key) io-names refs))
|
||||
(keys node)))
|
||||
(_ nil))))
|
||||
(define
|
||||
scan-io-refs
|
||||
:effects ()
|
||||
(fn
|
||||
(node (io-names :as list))
|
||||
(let ((refs (list))) (scan-io-refs-walk node io-names refs) refs)))
|
||||
(define
|
||||
transitive-io-refs-walk
|
||||
:effects ()
|
||||
(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)))
|
||||
(match
|
||||
(type-of val)
|
||||
("component"
|
||||
(do
|
||||
(for-each
|
||||
(fn
|
||||
((ref :as string))
|
||||
(when
|
||||
(not (contains? all-refs ref))
|
||||
(append! all-refs ref)))
|
||||
(scan-io-refs (component-body val) io-names))
|
||||
(for-each
|
||||
(fn
|
||||
((dep :as string))
|
||||
(transitive-io-refs-walk dep seen all-refs env io-names))
|
||||
(scan-refs (component-body val)))))
|
||||
("macro"
|
||||
(do
|
||||
(for-each
|
||||
(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 :as string))
|
||||
(transitive-io-refs-walk dep seen all-refs env io-names))
|
||||
(scan-refs (macro-body val)))))
|
||||
(_ nil))))))
|
||||
(define
|
||||
transitive-io-refs
|
||||
:effects ()
|
||||
(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))))
|
||||
(transitive-io-refs-walk key seen all-refs env io-names)
|
||||
all-refs)))
|
||||
(define
|
||||
compute-all-io-refs
|
||||
:effects (mutation)
|
||||
(fn
|
||||
((env :as dict) (io-names :as list))
|
||||
(for-each
|
||||
(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)))))
|
||||
(env-components env))))
|
||||
(define
|
||||
component-io-refs-cached
|
||||
:effects ()
|
||||
(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")
|
||||
(not (nil? (component-io-refs val)))
|
||||
(not (empty? (component-io-refs val))))
|
||||
(component-io-refs val)
|
||||
(transitive-io-refs name env io-names))))))
|
||||
(define
|
||||
component-pure?
|
||||
:effects ()
|
||||
(fn
|
||||
(name (env :as dict) (io-names :as list))
|
||||
(let
|
||||
((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let
|
||||
((val (if (env-has? env key) (env-get env key) nil)))
|
||||
(if
|
||||
(and
|
||||
(= (type-of val) "component")
|
||||
(not (nil? (component-io-refs val)))
|
||||
(not (empty? (component-io-refs val))))
|
||||
false
|
||||
(empty? (transitive-io-refs name env io-names)))))))
|
||||
(define
|
||||
render-target
|
||||
:effects ()
|
||||
(fn
|
||||
(name (env :as dict) (io-names :as list))
|
||||
(let
|
||||
((key (if (starts-with? name "~") name (str "~" name))))
|
||||
(let
|
||||
((val (if (env-has? env key) (env-get env key) nil)))
|
||||
(if
|
||||
(not (= (type-of val) "component"))
|
||||
"server"
|
||||
(match
|
||||
(component-affinity val)
|
||||
("server" "server")
|
||||
("client" "client")
|
||||
(_
|
||||
(if
|
||||
(not (component-pure? name env io-names))
|
||||
"server"
|
||||
"client"))))))))
|
||||
(define
|
||||
page-render-plan
|
||||
:effects ()
|
||||
(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))
|
||||
(client-list (list))
|
||||
(io-deps (list)))
|
||||
(for-each
|
||||
(fn
|
||||
((name :as string))
|
||||
(let
|
||||
((target (render-target name env io-names)))
|
||||
(dict-set! comp-targets name target)
|
||||
(if
|
||||
(= target "server")
|
||||
(do
|
||||
(append! server-list name)
|
||||
(for-each
|
||||
(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)))
|
||||
(append! client-list name))))
|
||||
needed)
|
||||
{:io-deps io-deps :server server-list :components comp-targets :client client-list})))
|
||||
(define
|
||||
env-components
|
||||
:effects ()
|
||||
(fn
|
||||
((env :as dict))
|
||||
(filter
|
||||
(fn
|
||||
((k :as string))
|
||||
(let ((v (env-get env k))) (or (component? v) (macro? v))))
|
||||
(keys env)))))) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web deps))
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user