Transpile signals.sx to JS and Python via bootstrappers
Both bootstrappers now handle the full signal runtime: - &rest lambda params → JS arguments.slice / Python *args - Signal/Island/TrackingContext platform functions in both hosts - RENAMES for all signal, island, tracking, and reactive DOM identifiers - signals auto-included with DOM adapter (JS) and HTML adapter (Python) - Signal API exports on Sx object (signal, deref, reset, swap, computed, effect, batch) - New DOM primitives: createComment, domRemove, domChildNodes, domRemoveChildrenAfter, domSetData - jsonSerialize/isEmptyDict for island state serialization - Demo HTML page exercising all signal primitives Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ from typing import Any
|
||||
# =========================================================================
|
||||
|
||||
from shared.sx.types import (
|
||||
NIL, Symbol, Keyword, Lambda, Component, Continuation, Macro,
|
||||
NIL, Symbol, Keyword, Lambda, Component, Island, Continuation, Macro,
|
||||
HandlerDef, QueryDef, ActionDef, PageDef, _ShiftSignal,
|
||||
)
|
||||
from shared.sx.parser import SxExpr
|
||||
@@ -122,6 +122,10 @@ def type_of(x):
|
||||
return "lambda"
|
||||
if isinstance(x, Component):
|
||||
return "component"
|
||||
if isinstance(x, Island):
|
||||
return "island"
|
||||
if isinstance(x, _Signal):
|
||||
return "signal"
|
||||
if isinstance(x, Macro):
|
||||
return "macro"
|
||||
if isinstance(x, _RawHTML):
|
||||
@@ -160,6 +164,11 @@ def make_component(name, params, has_children, body, env, affinity="auto"):
|
||||
body=body, closure=dict(env), affinity=str(affinity) if affinity else "auto")
|
||||
|
||||
|
||||
def make_island(name, params, has_children, body, env):
|
||||
return Island(name=name, params=list(params), has_children=has_children,
|
||||
body=body, closure=dict(env))
|
||||
|
||||
|
||||
def make_macro(params, rest_param, body, env, name=None):
|
||||
return Macro(params=list(params), rest_param=rest_param, body=body,
|
||||
closure=dict(env), name=name)
|
||||
@@ -294,6 +303,119 @@ def is_macro(x):
|
||||
return isinstance(x, Macro)
|
||||
|
||||
|
||||
def is_island(x):
|
||||
return isinstance(x, Island)
|
||||
|
||||
|
||||
def is_identical(a, b):
|
||||
return a is b
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Signal platform -- reactive state primitives
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class _Signal:
|
||||
"""Reactive signal container."""
|
||||
__slots__ = ("value", "subscribers", "deps")
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
self.subscribers = []
|
||||
self.deps = []
|
||||
|
||||
|
||||
class _TrackingContext:
|
||||
"""Context for discovering signal dependencies."""
|
||||
__slots__ = ("notify_fn", "deps")
|
||||
def __init__(self, notify_fn):
|
||||
self.notify_fn = notify_fn
|
||||
self.deps = []
|
||||
|
||||
|
||||
_tracking_context = None
|
||||
|
||||
|
||||
def make_signal(value):
|
||||
return _Signal(value)
|
||||
|
||||
|
||||
def is_signal(x):
|
||||
return isinstance(x, _Signal)
|
||||
|
||||
|
||||
def signal_value(s):
|
||||
return s.value if isinstance(s, _Signal) else s
|
||||
|
||||
|
||||
def signal_set_value(s, v):
|
||||
if isinstance(s, _Signal):
|
||||
s.value = v
|
||||
|
||||
|
||||
def signal_subscribers(s):
|
||||
return list(s.subscribers) if isinstance(s, _Signal) else []
|
||||
|
||||
|
||||
def signal_add_sub(s, fn):
|
||||
if isinstance(s, _Signal) and fn not in s.subscribers:
|
||||
s.subscribers.append(fn)
|
||||
|
||||
|
||||
def signal_remove_sub(s, fn):
|
||||
if isinstance(s, _Signal) and fn in s.subscribers:
|
||||
s.subscribers.remove(fn)
|
||||
|
||||
|
||||
def signal_deps(s):
|
||||
return list(s.deps) if isinstance(s, _Signal) else []
|
||||
|
||||
|
||||
def signal_set_deps(s, deps):
|
||||
if isinstance(s, _Signal):
|
||||
s.deps = list(deps) if isinstance(deps, list) else []
|
||||
|
||||
|
||||
def set_tracking_context(ctx):
|
||||
global _tracking_context
|
||||
_tracking_context = ctx
|
||||
|
||||
|
||||
def get_tracking_context():
|
||||
global _tracking_context
|
||||
return _tracking_context if _tracking_context is not None else NIL
|
||||
|
||||
|
||||
def make_tracking_context(notify_fn):
|
||||
return _TrackingContext(notify_fn)
|
||||
|
||||
|
||||
def tracking_context_deps(ctx):
|
||||
return ctx.deps if isinstance(ctx, _TrackingContext) else []
|
||||
|
||||
|
||||
def tracking_context_add_dep(ctx, s):
|
||||
if isinstance(ctx, _TrackingContext) and s not in ctx.deps:
|
||||
ctx.deps.append(s)
|
||||
|
||||
|
||||
def tracking_context_notify_fn(ctx):
|
||||
return ctx.notify_fn if isinstance(ctx, _TrackingContext) else NIL
|
||||
|
||||
|
||||
def json_serialize(obj):
|
||||
import json
|
||||
try:
|
||||
return json.dumps(obj)
|
||||
except (TypeError, ValueError):
|
||||
return "{}"
|
||||
|
||||
|
||||
def is_empty_dict(d):
|
||||
if not isinstance(d, dict):
|
||||
return True
|
||||
return len(d) == 0
|
||||
|
||||
|
||||
def env_has(env, name):
|
||||
return name in env
|
||||
|
||||
@@ -890,54 +1012,6 @@ has_key_p = PRIMITIVES["has-key?"]
|
||||
dissoc = PRIMITIVES["dissoc"]
|
||||
|
||||
|
||||
# =========================================================================
|
||||
# Platform: deps module — component dependency analysis
|
||||
# =========================================================================
|
||||
|
||||
import re as _re
|
||||
|
||||
def component_deps(c):
|
||||
"""Return cached deps list for a component (may be empty)."""
|
||||
return list(c.deps) if hasattr(c, "deps") and c.deps else []
|
||||
|
||||
def component_set_deps(c, deps):
|
||||
"""Cache deps on a component."""
|
||||
c.deps = set(deps) if not isinstance(deps, set) else deps
|
||||
|
||||
def component_css_classes(c):
|
||||
"""Return pre-scanned CSS class list for a component."""
|
||||
return list(c.css_classes) if hasattr(c, "css_classes") and c.css_classes else []
|
||||
|
||||
def env_components(env):
|
||||
"""Return list of component/macro names in an environment."""
|
||||
return [k for k, v in env.items()
|
||||
if isinstance(v, (Component, Macro))]
|
||||
|
||||
def regex_find_all(pattern, source):
|
||||
"""Return list of capture group 1 matches."""
|
||||
return [m.group(1) for m in _re.finditer(pattern, source)]
|
||||
|
||||
def scan_css_classes(source):
|
||||
"""Extract CSS class strings from SX source."""
|
||||
classes = set()
|
||||
for m in _re.finditer(r':class\s+"([^"]*)"', source):
|
||||
classes.update(m.group(1).split())
|
||||
for m in _re.finditer(r':class\s+\(str\s+((?:"[^"]*"\s*)+)\)', source):
|
||||
for s in _re.findall(r'"([^"]*)"', m.group(1)):
|
||||
classes.update(s.split())
|
||||
for m in _re.finditer(r';;\s*@css\s+(.+)', source):
|
||||
classes.update(m.group(1).split())
|
||||
return list(classes)
|
||||
|
||||
def component_io_refs(c):
|
||||
"""Return cached IO refs list for a component (may be empty)."""
|
||||
return list(c.io_refs) if hasattr(c, "io_refs") and c.io_refs else []
|
||||
|
||||
def component_set_io_refs(c, refs):
|
||||
"""Cache IO refs on a component."""
|
||||
c.io_refs = set(refs) if not isinstance(refs, set) else refs
|
||||
|
||||
|
||||
# === Transpiled from eval ===
|
||||
|
||||
# trampoline
|
||||
@@ -947,10 +1021,10 @@ trampoline = lambda val: (lambda result: (trampoline(eval_expr(thunk_expr(result
|
||||
eval_expr = lambda expr, env: _sx_case(type_of(expr), [('number', lambda: expr), ('string', lambda: expr), ('boolean', lambda: expr), ('nil', lambda: NIL), ('symbol', lambda: (lambda name: (env_get(env, name) if sx_truthy(env_has(env, name)) else (get_primitive(name) if sx_truthy(is_primitive(name)) else (True if sx_truthy((name == 'true')) else (False if sx_truthy((name == 'false')) else (NIL if sx_truthy((name == 'nil')) else error(sx_str('Undefined symbol: ', name))))))))(symbol_name(expr))), ('keyword', lambda: keyword_name(expr)), ('dict', lambda: map_dict(lambda k, v: trampoline(eval_expr(v, env)), expr)), ('list', lambda: ([] if sx_truthy(empty_p(expr)) else eval_list(expr, env))), (None, lambda: expr)])
|
||||
|
||||
# eval-list
|
||||
eval_list = lambda expr, env: (lambda head: (lambda args: (map(lambda x: trampoline(eval_expr(x, env)), expr) if sx_truthy((not sx_truthy(((type_of(head) == 'symbol') if sx_truthy((type_of(head) == 'symbol')) else ((type_of(head) == 'lambda') if sx_truthy((type_of(head) == 'lambda')) else (type_of(head) == 'list')))))) else ((lambda name: (sf_if(args, env) if sx_truthy((name == 'if')) else (sf_when(args, env) if sx_truthy((name == 'when')) else (sf_cond(args, env) if sx_truthy((name == 'cond')) else (sf_case(args, env) if sx_truthy((name == 'case')) else (sf_and(args, env) if sx_truthy((name == 'and')) else (sf_or(args, env) if sx_truthy((name == 'or')) else (sf_let(args, env) if sx_truthy((name == 'let')) else (sf_let(args, env) if sx_truthy((name == 'let*')) else (sf_letrec(args, env) if sx_truthy((name == 'letrec')) else (sf_lambda(args, env) if sx_truthy((name == 'lambda')) else (sf_lambda(args, env) if sx_truthy((name == 'fn')) else (sf_define(args, env) if sx_truthy((name == 'define')) else (sf_defcomp(args, env) if sx_truthy((name == 'defcomp')) else (sf_defmacro(args, env) if sx_truthy((name == 'defmacro')) else (sf_defstyle(args, env) if sx_truthy((name == 'defstyle')) else (sf_defhandler(args, env) if sx_truthy((name == 'defhandler')) else (sf_defpage(args, env) if sx_truthy((name == 'defpage')) else (sf_defquery(args, env) if sx_truthy((name == 'defquery')) else (sf_defaction(args, env) if sx_truthy((name == 'defaction')) else (sf_begin(args, env) if sx_truthy((name == 'begin')) else (sf_begin(args, env) if sx_truthy((name == 'do')) else (sf_quote(args, env) if sx_truthy((name == 'quote')) else (sf_quasiquote(args, env) if sx_truthy((name == 'quasiquote')) else (sf_thread_first(args, env) if sx_truthy((name == '->')) else (sf_set_bang(args, env) if sx_truthy((name == 'set!')) else (sf_reset(args, env) if sx_truthy((name == 'reset')) else (sf_shift(args, env) if sx_truthy((name == 'shift')) else (sf_dynamic_wind(args, env) if sx_truthy((name == 'dynamic-wind')) else (ho_map(args, env) if sx_truthy((name == 'map')) else (ho_map_indexed(args, env) if sx_truthy((name == 'map-indexed')) else (ho_filter(args, env) if sx_truthy((name == 'filter')) else (ho_reduce(args, env) if sx_truthy((name == 'reduce')) else (ho_some(args, env) if sx_truthy((name == 'some')) else (ho_every(args, env) if sx_truthy((name == 'every?')) else (ho_for_each(args, env) if sx_truthy((name == 'for-each')) else ((lambda mac: make_thunk(expand_macro(mac, args, env), env))(env_get(env, name)) if sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))) else (render_expr(expr, env) if sx_truthy(is_render_expr(expr)) else eval_call(head, args, env)))))))))))))))))))))))))))))))))))))))(symbol_name(head)) if sx_truthy((type_of(head) == 'symbol')) else eval_call(head, args, env))))(rest(expr)))(first(expr))
|
||||
eval_list = lambda expr, env: (lambda head: (lambda args: (map(lambda x: trampoline(eval_expr(x, env)), expr) if sx_truthy((not sx_truthy(((type_of(head) == 'symbol') if sx_truthy((type_of(head) == 'symbol')) else ((type_of(head) == 'lambda') if sx_truthy((type_of(head) == 'lambda')) else (type_of(head) == 'list')))))) else ((lambda name: (sf_if(args, env) if sx_truthy((name == 'if')) else (sf_when(args, env) if sx_truthy((name == 'when')) else (sf_cond(args, env) if sx_truthy((name == 'cond')) else (sf_case(args, env) if sx_truthy((name == 'case')) else (sf_and(args, env) if sx_truthy((name == 'and')) else (sf_or(args, env) if sx_truthy((name == 'or')) else (sf_let(args, env) if sx_truthy((name == 'let')) else (sf_let(args, env) if sx_truthy((name == 'let*')) else (sf_letrec(args, env) if sx_truthy((name == 'letrec')) else (sf_lambda(args, env) if sx_truthy((name == 'lambda')) else (sf_lambda(args, env) if sx_truthy((name == 'fn')) else (sf_define(args, env) if sx_truthy((name == 'define')) else (sf_defcomp(args, env) if sx_truthy((name == 'defcomp')) else (sf_defisland(args, env) if sx_truthy((name == 'defisland')) else (sf_defmacro(args, env) if sx_truthy((name == 'defmacro')) else (sf_defstyle(args, env) if sx_truthy((name == 'defstyle')) else (sf_defhandler(args, env) if sx_truthy((name == 'defhandler')) else (sf_defpage(args, env) if sx_truthy((name == 'defpage')) else (sf_defquery(args, env) if sx_truthy((name == 'defquery')) else (sf_defaction(args, env) if sx_truthy((name == 'defaction')) else (sf_begin(args, env) if sx_truthy((name == 'begin')) else (sf_begin(args, env) if sx_truthy((name == 'do')) else (sf_quote(args, env) if sx_truthy((name == 'quote')) else (sf_quasiquote(args, env) if sx_truthy((name == 'quasiquote')) else (sf_thread_first(args, env) if sx_truthy((name == '->')) else (sf_set_bang(args, env) if sx_truthy((name == 'set!')) else (sf_reset(args, env) if sx_truthy((name == 'reset')) else (sf_shift(args, env) if sx_truthy((name == 'shift')) else (sf_dynamic_wind(args, env) if sx_truthy((name == 'dynamic-wind')) else (ho_map(args, env) if sx_truthy((name == 'map')) else (ho_map_indexed(args, env) if sx_truthy((name == 'map-indexed')) else (ho_filter(args, env) if sx_truthy((name == 'filter')) else (ho_reduce(args, env) if sx_truthy((name == 'reduce')) else (ho_some(args, env) if sx_truthy((name == 'some')) else (ho_every(args, env) if sx_truthy((name == 'every?')) else (ho_for_each(args, env) if sx_truthy((name == 'for-each')) else ((lambda mac: make_thunk(expand_macro(mac, args, env), env))(env_get(env, name)) if sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))) else (render_expr(expr, env) if sx_truthy(is_render_expr(expr)) else eval_call(head, args, env))))))))))))))))))))))))))))))))))))))))(symbol_name(head)) if sx_truthy((type_of(head) == 'symbol')) else eval_call(head, args, env))))(rest(expr)))(first(expr))
|
||||
|
||||
# eval-call
|
||||
eval_call = lambda head, args, env: (lambda f: (lambda evaluated_args: (apply(f, evaluated_args) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else ((not sx_truthy(is_lambda(f))) if not sx_truthy((not sx_truthy(is_lambda(f)))) else (not sx_truthy(is_component(f)))))) else (call_lambda(f, evaluated_args, env) if sx_truthy(is_lambda(f)) else (call_component(f, args, env) if sx_truthy(is_component(f)) else error(sx_str('Not callable: ', inspect(f)))))))(map(lambda a: trampoline(eval_expr(a, env)), args)))(trampoline(eval_expr(head, env)))
|
||||
eval_call = lambda head, args, env: (lambda f: (lambda evaluated_args: (apply(f, evaluated_args) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else ((not sx_truthy(is_lambda(f))) if not sx_truthy((not sx_truthy(is_lambda(f)))) else ((not sx_truthy(is_component(f))) if not sx_truthy((not sx_truthy(is_component(f)))) else (not sx_truthy(is_island(f))))))) else (call_lambda(f, evaluated_args, env) if sx_truthy(is_lambda(f)) else (call_component(f, args, env) if sx_truthy(is_component(f)) else (call_component(f, args, env) if sx_truthy(is_island(f)) else error(sx_str('Not callable: ', inspect(f))))))))(map(lambda a: trampoline(eval_expr(a, env)), args)))(trampoline(eval_expr(head, env)))
|
||||
|
||||
# call-lambda
|
||||
call_lambda = lambda f, args, caller_env: (lambda params: (lambda local: (error(sx_str((lambda_name(f) if sx_truthy(lambda_name(f)) else 'lambda'), ' expects ', len(params), ' args, got ', len(args))) if sx_truthy((len(args) != len(params))) else _sx_begin(for_each(lambda pair: _sx_dict_set(local, first(pair), nth(pair, 1)), zip(params, args)), make_thunk(lambda_body(f), local))))(env_merge(lambda_closure(f), caller_env)))(lambda_params(f))
|
||||
@@ -1040,6 +1114,9 @@ def parse_comp_params(params_expr):
|
||||
params.append(name)
|
||||
return [params, _cells['has_children']]
|
||||
|
||||
# sf-defisland
|
||||
sf_defisland = lambda args, env: (lambda name_sym: (lambda params_raw: (lambda body: (lambda comp_name: (lambda parsed: (lambda params: (lambda has_children: (lambda island: _sx_begin(_sx_dict_set(env, symbol_name(name_sym), island), island))(make_island(comp_name, params, has_children, body, env)))(nth(parsed, 1)))(first(parsed)))(parse_comp_params(params_raw)))(strip_prefix(symbol_name(name_sym), '~')))(last(args)))(nth(args, 1)))(first(args))
|
||||
|
||||
# sf-defmacro
|
||||
sf_defmacro = lambda args, env: (lambda name_sym: (lambda params_raw: (lambda body: (lambda parsed: (lambda params: (lambda rest_param: (lambda mac: _sx_begin(_sx_dict_set(env, symbol_name(name_sym), mac), mac))(make_macro(params, rest_param, body, env, symbol_name(name_sym))))(nth(parsed, 1)))(first(parsed)))(parse_macro_params(params_raw)))(nth(args, 2)))(nth(args, 1)))(first(args))
|
||||
|
||||
@@ -1164,7 +1241,7 @@ VOID_ELEMENTS = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'li
|
||||
BOOLEAN_ATTRS = ['async', 'autofocus', 'autoplay', 'checked', 'controls', 'default', 'defer', 'disabled', 'formnovalidate', 'hidden', 'inert', 'ismap', 'loop', 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'playsinline', 'readonly', 'required', 'reversed', 'selected']
|
||||
|
||||
# definition-form?
|
||||
is_definition_form = lambda name: ((name == 'define') if sx_truthy((name == 'define')) else ((name == 'defcomp') if sx_truthy((name == 'defcomp')) else ((name == 'defmacro') if sx_truthy((name == 'defmacro')) else ((name == 'defstyle') if sx_truthy((name == 'defstyle')) else (name == 'defhandler')))))
|
||||
is_definition_form = lambda name: ((name == 'define') if sx_truthy((name == 'define')) else ((name == 'defcomp') if sx_truthy((name == 'defcomp')) else ((name == 'defisland') if sx_truthy((name == 'defisland')) else ((name == 'defmacro') if sx_truthy((name == 'defmacro')) else ((name == 'defstyle') if sx_truthy((name == 'defstyle')) else (name == 'defhandler'))))))
|
||||
|
||||
# parse-element-args
|
||||
parse_element_args = lambda args, env: (lambda attrs: (lambda children: _sx_begin(reduce(lambda state, arg: (lambda skip: (assoc(state, 'skip', False, 'i', (get(state, 'i') + 1)) if sx_truthy(skip) else ((lambda val: _sx_begin(_sx_dict_set(attrs, keyword_name(arg), val), assoc(state, 'skip', True, 'i', (get(state, 'i') + 1))))(trampoline(eval_expr(nth(args, (get(state, 'i') + 1)), env))) if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((get(state, 'i') + 1) < len(args)))) else _sx_begin(_sx_append(children, arg), assoc(state, 'i', (get(state, 'i') + 1))))))(get(state, 'skip')), {'i': 0, 'skip': False}, args), [attrs, children]))([]))({})
|
||||
@@ -1194,13 +1271,13 @@ render_to_html = lambda expr, env: _sx_case(type_of(expr), [('nil', lambda: ''),
|
||||
render_value_to_html = lambda val, env: _sx_case(type_of(val), [('nil', lambda: ''), ('string', lambda: escape_html(val)), ('number', lambda: sx_str(val)), ('boolean', lambda: ('true' if sx_truthy(val) else 'false')), ('list', lambda: render_list_to_html(val, env)), ('raw-html', lambda: raw_html_content(val)), (None, lambda: escape_html(sx_str(val)))])
|
||||
|
||||
# RENDER_HTML_FORMS
|
||||
RENDER_HTML_FORMS = ['if', 'when', 'cond', 'case', 'let', 'let*', 'begin', 'do', 'define', 'defcomp', 'defmacro', 'defstyle', 'defhandler', 'map', 'map-indexed', 'filter', 'for-each']
|
||||
RENDER_HTML_FORMS = ['if', 'when', 'cond', 'case', 'let', 'let*', 'begin', 'do', 'define', 'defcomp', 'defisland', 'defmacro', 'defstyle', 'defhandler', 'map', 'map-indexed', 'filter', 'for-each']
|
||||
|
||||
# render-html-form?
|
||||
is_render_html_form = lambda name: contains_p(RENDER_HTML_FORMS, name)
|
||||
|
||||
# render-list-to-html
|
||||
render_list_to_html = lambda expr, env: ('' if sx_truthy(empty_p(expr)) else (lambda head: (join('', map(lambda x: render_value_to_html(x, env), expr)) if sx_truthy((not sx_truthy((type_of(head) == 'symbol')))) else (lambda name: (lambda args: (join('', map(lambda x: render_to_html(x, env), args)) if sx_truthy((name == '<>')) else (join('', map(lambda x: sx_str(trampoline(eval_expr(x, env))), args)) if sx_truthy((name == 'raw!')) else (render_html_element(name, args, env) if sx_truthy(contains_p(HTML_TAGS, name)) else ((lambda val: (render_html_component(val, args, env) if sx_truthy(is_component(val)) else (render_to_html(expand_macro(val, args, env), env) if sx_truthy(is_macro(val)) else error(sx_str('Unknown component: ', name)))))(env_get(env, name)) if sx_truthy(starts_with_p(name, '~')) else (dispatch_html_form(name, expr, env) if sx_truthy(is_render_html_form(name)) else (render_to_html(expand_macro(env_get(env, name), args, env), env) if sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))) else render_value_to_html(trampoline(eval_expr(expr, env)), env))))))))(rest(expr)))(symbol_name(head))))(first(expr)))
|
||||
render_list_to_html = lambda expr, env: ('' if sx_truthy(empty_p(expr)) else (lambda head: (join('', map(lambda x: render_value_to_html(x, env), expr)) if sx_truthy((not sx_truthy((type_of(head) == 'symbol')))) else (lambda name: (lambda args: (join('', map(lambda x: render_to_html(x, env), args)) if sx_truthy((name == '<>')) else (join('', map(lambda x: sx_str(trampoline(eval_expr(x, env))), args)) if sx_truthy((name == 'raw!')) else (render_html_element(name, args, env) if sx_truthy(contains_p(HTML_TAGS, name)) else (render_html_island(env_get(env, name), args, env) if sx_truthy((starts_with_p(name, '~') if not sx_truthy(starts_with_p(name, '~')) else (env_has(env, name) if not sx_truthy(env_has(env, name)) else is_island(env_get(env, name))))) else ((lambda val: (render_html_component(val, args, env) if sx_truthy(is_component(val)) else (render_to_html(expand_macro(val, args, env), env) if sx_truthy(is_macro(val)) else error(sx_str('Unknown component: ', name)))))(env_get(env, name)) if sx_truthy(starts_with_p(name, '~')) else (dispatch_html_form(name, expr, env) if sx_truthy(is_render_html_form(name)) else (render_to_html(expand_macro(env_get(env, name), args, env), env) if sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))) else render_value_to_html(trampoline(eval_expr(expr, env)), env)))))))))(rest(expr)))(symbol_name(head))))(first(expr)))
|
||||
|
||||
# dispatch-html-form
|
||||
dispatch_html_form = lambda name, expr, env: ((lambda cond_val: (render_to_html(nth(expr, 2), env) if sx_truthy(cond_val) else (render_to_html(nth(expr, 3), env) if sx_truthy((len(expr) > 3)) else '')))(trampoline(eval_expr(nth(expr, 1), env))) if sx_truthy((name == 'if')) else (('' if sx_truthy((not sx_truthy(trampoline(eval_expr(nth(expr, 1), env))))) else join('', map(lambda i: render_to_html(nth(expr, i), env), range(2, len(expr))))) if sx_truthy((name == 'when')) else ((lambda branch: (render_to_html(branch, env) if sx_truthy(branch) else ''))(eval_cond(rest(expr), env)) if sx_truthy((name == 'cond')) else (render_to_html(trampoline(eval_expr(expr, env)), env) if sx_truthy((name == 'case')) else ((lambda local: join('', map(lambda i: render_to_html(nth(expr, i), local), range(2, len(expr)))))(process_bindings(nth(expr, 1), env)) if sx_truthy(((name == 'let') if sx_truthy((name == 'let')) else (name == 'let*'))) else (join('', map(lambda i: render_to_html(nth(expr, i), env), range(1, len(expr)))) if sx_truthy(((name == 'begin') if sx_truthy((name == 'begin')) else (name == 'do'))) else (_sx_begin(trampoline(eval_expr(expr, env)), '') if sx_truthy(is_definition_form(name)) else ((lambda f: (lambda coll: join('', map(lambda item: (render_lambda_html(f, [item], env) if sx_truthy(is_lambda(f)) else render_to_html(apply(f, [item]), env)), coll)))(trampoline(eval_expr(nth(expr, 2), env))))(trampoline(eval_expr(nth(expr, 1), env))) if sx_truthy((name == 'map')) else ((lambda f: (lambda coll: join('', map_indexed(lambda i, item: (render_lambda_html(f, [i, item], env) if sx_truthy(is_lambda(f)) else render_to_html(apply(f, [i, item]), env)), coll)))(trampoline(eval_expr(nth(expr, 2), env))))(trampoline(eval_expr(nth(expr, 1), env))) if sx_truthy((name == 'map-indexed')) else (render_to_html(trampoline(eval_expr(expr, env)), env) if sx_truthy((name == 'filter')) else ((lambda f: (lambda coll: join('', map(lambda item: (render_lambda_html(f, [item], env) if sx_truthy(is_lambda(f)) else render_to_html(apply(f, [item]), env)), coll)))(trampoline(eval_expr(nth(expr, 2), env))))(trampoline(eval_expr(nth(expr, 1), env))) if sx_truthy((name == 'for-each')) else render_value_to_html(trampoline(eval_expr(expr, env)), env))))))))))))
|
||||
@@ -1214,6 +1291,12 @@ render_html_component = lambda comp, args, env: (lambda kwargs: (lambda children
|
||||
# render-html-element
|
||||
render_html_element = lambda tag, args, env: (lambda parsed: (lambda attrs: (lambda children: (lambda is_void: sx_str('<', tag, render_attrs(attrs), (' />' if sx_truthy(is_void) else sx_str('>', join('', map(lambda c: render_to_html(c, env), children)), '</', tag, '>'))))(contains_p(VOID_ELEMENTS, tag)))(nth(parsed, 1)))(first(parsed)))(parse_element_args(args, env))
|
||||
|
||||
# render-html-island
|
||||
render_html_island = lambda island, args, env: (lambda kwargs: (lambda children: _sx_begin(reduce(lambda state, arg: (lambda skip: (assoc(state, 'skip', False, 'i', (get(state, 'i') + 1)) if sx_truthy(skip) else ((lambda val: _sx_begin(_sx_dict_set(kwargs, keyword_name(arg), val), assoc(state, 'skip', True, 'i', (get(state, 'i') + 1))))(trampoline(eval_expr(nth(args, (get(state, 'i') + 1)), env))) if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((get(state, 'i') + 1) < len(args)))) else _sx_begin(_sx_append(children, arg), assoc(state, 'i', (get(state, 'i') + 1))))))(get(state, 'skip')), {'i': 0, 'skip': False}, args), (lambda local: (lambda island_name: _sx_begin(for_each(lambda p: _sx_dict_set(local, p, (dict_get(kwargs, p) if sx_truthy(dict_has(kwargs, p)) else NIL)), component_params(island)), (_sx_dict_set(local, 'children', make_raw_html(join('', map(lambda c: render_to_html(c, env), children)))) if sx_truthy(component_has_children(island)) else NIL), (lambda body_html: (lambda state_json: sx_str('<div data-sx-island="', escape_attr(island_name), '"', (sx_str(' data-sx-state="', escape_attr(state_json), '"') if sx_truthy(state_json) else ''), '>', body_html, '</div>'))(serialize_island_state(kwargs)))(render_to_html(component_body(island), local))))(component_name(island)))(env_merge(component_closure(island), env))))([]))({})
|
||||
|
||||
# serialize-island-state
|
||||
serialize_island_state = lambda kwargs: (NIL if sx_truthy(is_empty_dict(kwargs)) else json_serialize(kwargs))
|
||||
|
||||
|
||||
# === Transpiled from adapter-sx ===
|
||||
|
||||
@@ -1224,7 +1307,7 @@ render_to_sx = lambda expr, env: (lambda result: (result if sx_truthy((type_of(r
|
||||
aser = lambda expr, env: _sx_case(type_of(expr), [('number', lambda: expr), ('string', lambda: expr), ('boolean', lambda: expr), ('nil', lambda: NIL), ('symbol', lambda: (lambda name: (env_get(env, name) if sx_truthy(env_has(env, name)) else (get_primitive(name) if sx_truthy(is_primitive(name)) else (True if sx_truthy((name == 'true')) else (False if sx_truthy((name == 'false')) else (NIL if sx_truthy((name == 'nil')) else error(sx_str('Undefined symbol: ', name))))))))(symbol_name(expr))), ('keyword', lambda: keyword_name(expr)), ('list', lambda: ([] if sx_truthy(empty_p(expr)) else aser_list(expr, env))), (None, lambda: expr)])
|
||||
|
||||
# aser-list
|
||||
aser_list = lambda expr, env: (lambda head: (lambda args: (map(lambda x: aser(x, env), expr) if sx_truthy((not sx_truthy((type_of(head) == 'symbol')))) else (lambda name: (aser_fragment(args, env) if sx_truthy((name == '<>')) else (aser_call(name, args, env) if sx_truthy(starts_with_p(name, '~')) else (aser_call(name, args, env) if sx_truthy(contains_p(HTML_TAGS, name)) else (aser_special(name, expr, env) if sx_truthy((is_special_form(name) if sx_truthy(is_special_form(name)) else is_ho_form(name))) else (aser(expand_macro(env_get(env, name), args, env), env) if sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))) else (lambda f: (lambda evaled_args: (apply(f, evaled_args) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else ((not sx_truthy(is_lambda(f))) if not sx_truthy((not sx_truthy(is_lambda(f)))) else (not sx_truthy(is_component(f)))))) else (trampoline(call_lambda(f, evaled_args, env)) if sx_truthy(is_lambda(f)) else (aser_call(sx_str('~', component_name(f)), args, env) if sx_truthy(is_component(f)) else error(sx_str('Not callable: ', inspect(f)))))))(map(lambda a: trampoline(eval_expr(a, env)), args)))(trampoline(eval_expr(head, env)))))))))(symbol_name(head))))(rest(expr)))(first(expr))
|
||||
aser_list = lambda expr, env: (lambda head: (lambda args: (map(lambda x: aser(x, env), expr) if sx_truthy((not sx_truthy((type_of(head) == 'symbol')))) else (lambda name: (aser_fragment(args, env) if sx_truthy((name == '<>')) else (aser_call(name, args, env) if sx_truthy(starts_with_p(name, '~')) else (aser_call(name, args, env) if sx_truthy(contains_p(HTML_TAGS, name)) else (aser_special(name, expr, env) if sx_truthy((is_special_form(name) if sx_truthy(is_special_form(name)) else is_ho_form(name))) else (aser(expand_macro(env_get(env, name), args, env), env) if sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))) else (lambda f: (lambda evaled_args: (apply(f, evaled_args) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else ((not sx_truthy(is_lambda(f))) if not sx_truthy((not sx_truthy(is_lambda(f)))) else ((not sx_truthy(is_component(f))) if not sx_truthy((not sx_truthy(is_component(f)))) else (not sx_truthy(is_island(f))))))) else (trampoline(call_lambda(f, evaled_args, env)) if sx_truthy(is_lambda(f)) else (aser_call(sx_str('~', component_name(f)), args, env) if sx_truthy(is_component(f)) else (aser_call(sx_str('~', component_name(f)), args, env) if sx_truthy(is_island(f)) else error(sx_str('Not callable: ', inspect(f))))))))(map(lambda a: trampoline(eval_expr(a, env)), args)))(trampoline(eval_expr(head, env)))))))))(symbol_name(head))))(rest(expr)))(first(expr))
|
||||
|
||||
# aser-fragment
|
||||
aser_fragment = lambda children, env: (lambda parts: ('' if sx_truthy(empty_p(parts)) else sx_str('(<> ', join(' ', map(serialize, parts)), ')')))(filter(lambda x: (not sx_truthy(is_nil(x))), map(lambda c: aser(c, env), children)))
|
||||
@@ -1233,61 +1316,77 @@ aser_fragment = lambda children, env: (lambda parts: ('' if sx_truthy(empty_p(pa
|
||||
aser_call = lambda name, args, env: (lambda parts: _sx_begin(reduce(lambda state, arg: (lambda skip: (assoc(state, 'skip', False, 'i', (get(state, 'i') + 1)) if sx_truthy(skip) else ((lambda val: _sx_begin((_sx_begin(_sx_append(parts, sx_str(':', keyword_name(arg))), _sx_append(parts, serialize(val))) if sx_truthy((not sx_truthy(is_nil(val)))) else NIL), assoc(state, 'skip', True, 'i', (get(state, 'i') + 1))))(aser(nth(args, (get(state, 'i') + 1)), env)) if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((get(state, 'i') + 1) < len(args)))) else (lambda val: _sx_begin((_sx_append(parts, serialize(val)) if sx_truthy((not sx_truthy(is_nil(val)))) else NIL), assoc(state, 'i', (get(state, 'i') + 1))))(aser(arg, env)))))(get(state, 'skip')), {'i': 0, 'skip': False}, args), sx_str('(', join(' ', parts), ')')))([name])
|
||||
|
||||
|
||||
# === Transpiled from deps (component dependency analysis) ===
|
||||
# === Transpiled from signals (reactive signal runtime) ===
|
||||
|
||||
# scan-refs
|
||||
scan_refs = lambda node: (lambda refs: _sx_begin(scan_refs_walk(node, refs), refs))([])
|
||||
# signal
|
||||
signal = lambda initial_value: make_signal(initial_value)
|
||||
|
||||
# scan-refs-walk
|
||||
scan_refs_walk = lambda node, refs: ((lambda name: ((_sx_append(refs, name) if sx_truthy((not sx_truthy(contains_p(refs, name)))) else NIL) if sx_truthy(starts_with_p(name, '~')) else NIL))(symbol_name(node)) if sx_truthy((type_of(node) == 'symbol')) else (for_each(lambda item: scan_refs_walk(item, refs), node) if sx_truthy((type_of(node) == 'list')) else (for_each(lambda key: scan_refs_walk(dict_get(node, key), refs), keys(node)) if sx_truthy((type_of(node) == 'dict')) else NIL)))
|
||||
# deref
|
||||
deref = lambda s: (s if sx_truthy((not sx_truthy(is_signal(s)))) else (lambda ctx: _sx_begin((_sx_begin(tracking_context_add_dep(ctx, s), signal_add_sub(s, tracking_context_notify_fn(ctx))) if sx_truthy(ctx) else NIL), signal_value(s)))(get_tracking_context()))
|
||||
|
||||
# transitive-deps-walk
|
||||
transitive_deps_walk = lambda n, seen, env: (_sx_begin(_sx_append(seen, n), (lambda val: (for_each(lambda ref: transitive_deps_walk(ref, seen, env), scan_refs(component_body(val))) if sx_truthy((type_of(val) == 'component')) else (for_each(lambda ref: transitive_deps_walk(ref, seen, env), scan_refs(macro_body(val))) if sx_truthy((type_of(val) == 'macro')) else NIL)))(env_get(env, n))) if sx_truthy((not sx_truthy(contains_p(seen, n)))) else NIL)
|
||||
# reset!
|
||||
reset_b = lambda s, value: ((lambda old: (_sx_begin(signal_set_value(s, value), notify_subscribers(s)) if sx_truthy((not sx_truthy(is_identical(old, value)))) else NIL))(signal_value(s)) if sx_truthy(is_signal(s)) else NIL)
|
||||
|
||||
# transitive-deps
|
||||
transitive_deps = lambda name, env: (lambda seen: (lambda key: _sx_begin(transitive_deps_walk(key, seen, env), filter(lambda x: (not sx_truthy((x == key))), seen)))((name if sx_truthy(starts_with_p(name, '~')) else sx_str('~', name))))([])
|
||||
# swap!
|
||||
swap_b = lambda s, f, *args: ((lambda old: (lambda new_val: (_sx_begin(signal_set_value(s, new_val), notify_subscribers(s)) if sx_truthy((not sx_truthy(is_identical(old, new_val)))) else NIL))(apply(f, cons(old, args))))(signal_value(s)) if sx_truthy(is_signal(s)) else NIL)
|
||||
|
||||
# compute-all-deps
|
||||
compute_all_deps = lambda env: for_each(lambda name: (lambda val: (component_set_deps(val, transitive_deps(name, env)) if sx_truthy((type_of(val) == 'component')) else NIL))(env_get(env, name)), env_components(env))
|
||||
# computed
|
||||
computed = lambda compute_fn: (lambda s: (lambda deps: (lambda compute_ctx: (lambda recompute: _sx_begin(recompute(), s))(_sx_fn(lambda : (
|
||||
for_each(lambda dep: signal_remove_sub(dep, recompute), signal_deps(s)),
|
||||
signal_set_deps(s, []),
|
||||
(lambda ctx: (lambda prev: _sx_begin(set_tracking_context(ctx), (lambda new_val: _sx_begin(set_tracking_context(prev), signal_set_deps(s, tracking_context_deps(ctx)), (lambda old: _sx_begin(signal_set_value(s, new_val), (notify_subscribers(s) if sx_truthy((not sx_truthy(is_identical(old, new_val)))) else NIL)))(signal_value(s))))(compute_fn())))(get_tracking_context()))(make_tracking_context(recompute))
|
||||
)[-1])))(NIL))([]))(make_signal(NIL))
|
||||
|
||||
# scan-components-from-source
|
||||
scan_components_from_source = lambda source: (lambda matches: map(lambda m: sx_str('~', m), matches))(regex_find_all('\\(~([a-zA-Z_][a-zA-Z0-9_\\-]*)', source))
|
||||
# effect
|
||||
def effect(effect_fn):
|
||||
_cells = {}
|
||||
_cells['deps'] = []
|
||||
_cells['disposed'] = False
|
||||
_cells['cleanup_fn'] = NIL
|
||||
run_effect = lambda : (_sx_begin((cleanup_fn() if sx_truthy(_cells['cleanup_fn']) else NIL), for_each(lambda dep: signal_remove_sub(dep, run_effect), _cells['deps']), _sx_cell_set(_cells, 'deps', []), (lambda ctx: (lambda prev: _sx_begin(set_tracking_context(ctx), (lambda result: _sx_begin(set_tracking_context(prev), _sx_cell_set(_cells, 'deps', tracking_context_deps(ctx)), (_sx_cell_set(_cells, 'cleanup_fn', result) if sx_truthy(is_callable(result)) else NIL)))(effect_fn())))(get_tracking_context()))(make_tracking_context(run_effect))) if sx_truthy((not sx_truthy(_cells['disposed']))) else NIL)
|
||||
run_effect()
|
||||
return _sx_fn(lambda : (
|
||||
_sx_cell_set(_cells, 'disposed', True),
|
||||
(cleanup_fn() if sx_truthy(_cells['cleanup_fn']) else NIL),
|
||||
for_each(lambda dep: signal_remove_sub(dep, run_effect), _cells['deps']),
|
||||
_sx_cell_set(_cells, 'deps', [])
|
||||
)[-1])
|
||||
|
||||
# components-needed
|
||||
components_needed = lambda page_source, env: (lambda direct: (lambda all_needed: _sx_begin(for_each(_sx_fn(lambda name: (
|
||||
(_sx_append(all_needed, name) if sx_truthy((not sx_truthy(contains_p(all_needed, name)))) else NIL),
|
||||
(lambda val: (lambda deps: for_each(lambda dep: (_sx_append(all_needed, dep) if sx_truthy((not sx_truthy(contains_p(all_needed, dep)))) else NIL), deps))((component_deps(val) if sx_truthy(((type_of(val) == 'component') if not sx_truthy((type_of(val) == 'component')) else (not sx_truthy(empty_p(component_deps(val)))))) else transitive_deps(name, env))))(env_get(env, name))
|
||||
)[-1]), direct), all_needed))([]))(scan_components_from_source(page_source))
|
||||
# *batch-depth*
|
||||
_batch_depth = 0
|
||||
|
||||
# page-component-bundle
|
||||
page_component_bundle = lambda page_source, env: components_needed(page_source, env)
|
||||
# *batch-queue*
|
||||
_batch_queue = []
|
||||
|
||||
# page-css-classes
|
||||
page_css_classes = lambda page_source, env: (lambda needed: (lambda classes: _sx_begin(for_each(lambda name: (lambda val: (for_each(lambda cls: (_sx_append(classes, cls) if sx_truthy((not sx_truthy(contains_p(classes, cls)))) else NIL), component_css_classes(val)) if sx_truthy((type_of(val) == 'component')) else NIL))(env_get(env, name)), needed), for_each(lambda cls: (_sx_append(classes, cls) if sx_truthy((not sx_truthy(contains_p(classes, cls)))) else NIL), scan_css_classes(page_source)), classes))([]))(components_needed(page_source, env))
|
||||
# batch
|
||||
def batch(thunk):
|
||||
_batch_depth = (_batch_depth + 1)
|
||||
thunk()
|
||||
_batch_depth = (_batch_depth - 1)
|
||||
return ((lambda queue: _sx_begin(_sx_cell_set(_cells, '_batch_queue', []), (lambda seen: (lambda pending: _sx_begin(for_each(lambda s: for_each(lambda sub: (_sx_begin(_sx_append(seen, sub), _sx_append(pending, sub)) if sx_truthy((not sx_truthy(contains_p(seen, sub)))) else NIL), signal_subscribers(s)), queue), for_each(lambda sub: sub(), pending)))([]))([])))(_batch_queue) if sx_truthy((_batch_depth == 0)) else NIL)
|
||||
|
||||
# scan-io-refs-walk
|
||||
scan_io_refs_walk = lambda node, io_names, refs: ((lambda name: ((_sx_append(refs, name) if sx_truthy((not sx_truthy(contains_p(refs, name)))) else NIL) if sx_truthy(contains_p(io_names, name)) else NIL))(symbol_name(node)) if sx_truthy((type_of(node) == 'symbol')) else (for_each(lambda item: scan_io_refs_walk(item, io_names, refs), node) if sx_truthy((type_of(node) == 'list')) else (for_each(lambda key: scan_io_refs_walk(dict_get(node, key), io_names, refs), keys(node)) if sx_truthy((type_of(node) == 'dict')) else NIL)))
|
||||
# notify-subscribers
|
||||
notify_subscribers = lambda s: ((_sx_append(_batch_queue, s) if sx_truthy((not sx_truthy(contains_p(_batch_queue, s)))) else NIL) if sx_truthy((_batch_depth > 0)) else flush_subscribers(s))
|
||||
|
||||
# scan-io-refs
|
||||
scan_io_refs = lambda node, io_names: (lambda refs: _sx_begin(scan_io_refs_walk(node, io_names, refs), refs))([])
|
||||
# flush-subscribers
|
||||
flush_subscribers = lambda s: for_each(lambda sub: sub(), signal_subscribers(s))
|
||||
|
||||
# transitive-io-refs-walk
|
||||
transitive_io_refs_walk = lambda n, seen, all_refs, env, io_names: (_sx_begin(_sx_append(seen, n), (lambda val: (_sx_begin(for_each(lambda ref: (_sx_append(all_refs, ref) if sx_truthy((not sx_truthy(contains_p(all_refs, ref)))) else NIL), scan_io_refs(component_body(val), io_names)), for_each(lambda dep: transitive_io_refs_walk(dep, seen, all_refs, env, io_names), scan_refs(component_body(val)))) if sx_truthy((type_of(val) == 'component')) else (_sx_begin(for_each(lambda ref: (_sx_append(all_refs, ref) if sx_truthy((not sx_truthy(contains_p(all_refs, ref)))) else NIL), scan_io_refs(macro_body(val), io_names)), for_each(lambda dep: transitive_io_refs_walk(dep, seen, all_refs, env, io_names), scan_refs(macro_body(val)))) if sx_truthy((type_of(val) == 'macro')) else NIL)))(env_get(env, n))) if sx_truthy((not sx_truthy(contains_p(seen, n)))) else NIL)
|
||||
# dispose-computed
|
||||
dispose_computed = lambda s: (_sx_begin(for_each(lambda dep: signal_remove_sub(dep, NIL), signal_deps(s)), signal_set_deps(s, [])) if sx_truthy(is_signal(s)) else NIL)
|
||||
|
||||
# transitive-io-refs
|
||||
transitive_io_refs = lambda name, env, io_names: (lambda all_refs: (lambda seen: (lambda key: _sx_begin(transitive_io_refs_walk(key, seen, all_refs, env, io_names), all_refs))((name if sx_truthy(starts_with_p(name, '~')) else sx_str('~', name))))([]))([])
|
||||
# *island-scope*
|
||||
_island_scope = NIL
|
||||
|
||||
# compute-all-io-refs
|
||||
compute_all_io_refs = lambda env, io_names: for_each(lambda name: (lambda val: (component_set_io_refs(val, transitive_io_refs(name, env, io_names)) if sx_truthy((type_of(val) == 'component')) else NIL))(env_get(env, name)), env_components(env))
|
||||
# with-island-scope
|
||||
def with_island_scope(scope_fn, body_fn):
|
||||
prev = _island_scope
|
||||
_island_scope = scope_fn
|
||||
result = body_fn()
|
||||
_island_scope = prev
|
||||
return result
|
||||
|
||||
# component-pure?
|
||||
component_pure_p = lambda name, env, io_names: empty_p(transitive_io_refs(name, env, io_names))
|
||||
|
||||
# render-target
|
||||
render_target = lambda name, env, io_names: (lambda key: (lambda val: ('server' if sx_truthy((not sx_truthy((type_of(val) == 'component')))) else (lambda affinity: ('server' if sx_truthy((affinity == 'server')) else ('client' if sx_truthy((affinity == 'client')) else ('server' if sx_truthy((not sx_truthy(component_pure_p(name, env, io_names)))) else 'client'))))(component_affinity(val))))(env_get(env, key)))((name if sx_truthy(starts_with_p(name, '~')) else sx_str('~', name)))
|
||||
|
||||
# page-render-plan
|
||||
page_render_plan = lambda page_source, env, io_names: (lambda needed: (lambda comp_targets: (lambda server_list: (lambda client_list: (lambda io_deps: _sx_begin(for_each(lambda name: (lambda target: _sx_begin(_sx_dict_set(comp_targets, name, target), (_sx_begin(_sx_append(server_list, name), for_each(lambda io_ref: (_sx_append(io_deps, io_ref) if sx_truthy((not sx_truthy(contains_p(io_deps, io_ref)))) else NIL), transitive_io_refs(name, env, io_names))) if sx_truthy((target == 'server')) else _sx_append(client_list, name))))(render_target(name, env, io_names)), needed), {'components': comp_targets, 'server': server_list, 'client': client_list, 'io-deps': io_deps}))([]))([]))([]))({}))(components_needed(page_source, env))
|
||||
# register-in-scope
|
||||
register_in_scope = lambda disposable: (_island_scope(disposable) if sx_truthy(_island_scope) else NIL)
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user