Refactor spread to use provide/emit! internally
Spreads now emit their attrs into the nearest element's provide scope instead of requiring per-child spread? checks at every intermediate layer. emit! is tolerant (no-op when no provider), so spreads in non-element contexts silently vanish. - adapter-html: element/lake/marsh wrap children in provide, collect emitted; removed 14 spread filters from fragment, forms, components - adapter-sx: aser wraps result to catch spread values from fn calls; aser-call uses provide with attr-parts/child-parts ordering - adapter-async: same pattern for both render and aser paths - adapter-dom: added emit! in spread dispatch + provide in element rendering; kept spread? checks for reactive/island and DOM safety - platform: emit! returns NIL when no provider instead of erroring - 3 new aser tests: stored spread, nested element, silent drop Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
# WARNING: special-forms.sx declares forms not in eval.sx: reset, shift
|
||||
# WARNING: eval.sx dispatches forms not in special-forms.sx: form?, provide
|
||||
"""
|
||||
sx_ref.py -- Generated from reference SX evaluator specification.
|
||||
|
||||
@@ -87,11 +85,9 @@ def sx_context(name, *default):
|
||||
|
||||
|
||||
def sx_emit(name, value):
|
||||
"""Append value to nearest enclosing provider's accumulator. Error if no provider."""
|
||||
"""Append value to nearest enclosing provider's accumulator. No-op if no provider."""
|
||||
if name in _provide_stacks and _provide_stacks[name]:
|
||||
_provide_stacks[name][-1]["emitted"].append(value)
|
||||
else:
|
||||
raise RuntimeError(f"No provider for emit!: {name}")
|
||||
return NIL
|
||||
|
||||
|
||||
@@ -2225,7 +2221,8 @@ def render_to_html(expr, env):
|
||||
elif _match == 'raw-html':
|
||||
return raw_html_content(expr)
|
||||
elif _match == 'spread':
|
||||
return expr
|
||||
sx_emit('element-attrs', spread_attrs(expr))
|
||||
return ''
|
||||
else:
|
||||
return render_value_to_html(trampoline(eval_expr(expr, env)), env)
|
||||
|
||||
@@ -2248,7 +2245,8 @@ def render_value_to_html(val, env):
|
||||
elif _match == 'raw-html':
|
||||
return raw_html_content(val)
|
||||
elif _match == 'spread':
|
||||
return val
|
||||
sx_emit('element-attrs', spread_attrs(val))
|
||||
return ''
|
||||
else:
|
||||
return escape_html(sx_str(val))
|
||||
|
||||
@@ -2266,12 +2264,12 @@ def render_list_to_html(expr, env):
|
||||
else:
|
||||
head = first(expr)
|
||||
if sx_truthy((not sx_truthy((type_of(head) == 'symbol')))):
|
||||
return join('', filter(lambda x: (not sx_truthy(is_spread(x))), map(lambda x: render_value_to_html(x, env), expr)))
|
||||
return join('', map(lambda x: render_value_to_html(x, env), expr))
|
||||
else:
|
||||
name = symbol_name(head)
|
||||
args = rest(expr)
|
||||
if sx_truthy((name == '<>')):
|
||||
return join('', filter(lambda x: (not sx_truthy(is_spread(x))), map(lambda x: render_to_html(x, env), args)))
|
||||
return join('', map(lambda x: render_to_html(x, env), args))
|
||||
elif sx_truthy((name == 'raw!')):
|
||||
return join('', map(lambda x: sx_str(trampoline(eval_expr(x, env))), args))
|
||||
elif sx_truthy((name == 'lake')):
|
||||
@@ -2315,8 +2313,7 @@ def dispatch_html_form(name, expr, env):
|
||||
if sx_truthy((len(expr) == 3)):
|
||||
return render_to_html(nth(expr, 2), env)
|
||||
else:
|
||||
results = map(lambda i: render_to_html(nth(expr, i), env), range(2, len(expr)))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), results))
|
||||
return join('', map(lambda i: render_to_html(nth(expr, i), env), range(2, len(expr))))
|
||||
elif sx_truthy((name == 'cond')):
|
||||
branch = eval_cond(rest(expr), env)
|
||||
if sx_truthy(branch):
|
||||
@@ -2330,38 +2327,36 @@ def dispatch_html_form(name, expr, env):
|
||||
if sx_truthy((len(expr) == 3)):
|
||||
return render_to_html(nth(expr, 2), local)
|
||||
else:
|
||||
results = map(lambda i: render_to_html(nth(expr, i), local), range(2, len(expr)))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), results))
|
||||
return join('', map(lambda i: render_to_html(nth(expr, i), local), range(2, len(expr))))
|
||||
elif sx_truthy(((name == 'begin') if sx_truthy((name == 'begin')) else (name == 'do'))):
|
||||
if sx_truthy((len(expr) == 2)):
|
||||
return render_to_html(nth(expr, 1), env)
|
||||
else:
|
||||
results = map(lambda i: render_to_html(nth(expr, i), env), range(1, len(expr)))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), results))
|
||||
return join('', map(lambda i: render_to_html(nth(expr, i), env), range(1, len(expr))))
|
||||
elif sx_truthy(is_definition_form(name)):
|
||||
trampoline(eval_expr(expr, env))
|
||||
return ''
|
||||
elif sx_truthy((name == 'map')):
|
||||
f = trampoline(eval_expr(nth(expr, 1), env))
|
||||
coll = trampoline(eval_expr(nth(expr, 2), env))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), map(lambda item: (render_lambda_html(f, [item], env) if sx_truthy(is_lambda(f)) else render_to_html(apply(f, [item]), env)), coll)))
|
||||
return 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))
|
||||
elif sx_truthy((name == 'map-indexed')):
|
||||
f = trampoline(eval_expr(nth(expr, 1), env))
|
||||
coll = trampoline(eval_expr(nth(expr, 2), env))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), 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)))
|
||||
return 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))
|
||||
elif sx_truthy((name == 'filter')):
|
||||
return render_to_html(trampoline(eval_expr(expr, env)), env)
|
||||
elif sx_truthy((name == 'for-each')):
|
||||
f = trampoline(eval_expr(nth(expr, 1), env))
|
||||
coll = trampoline(eval_expr(nth(expr, 2), env))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), map(lambda item: (render_lambda_html(f, [item], env) if sx_truthy(is_lambda(f)) else render_to_html(apply(f, [item]), env)), coll)))
|
||||
return 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))
|
||||
elif sx_truthy((name == 'provide')):
|
||||
prov_name = trampoline(eval_expr(nth(expr, 1), env))
|
||||
prov_val = trampoline(eval_expr(nth(expr, 2), env))
|
||||
body_start = 3
|
||||
body_count = (len(expr) - 3)
|
||||
provide_push(prov_name, prov_val)
|
||||
result = (render_to_html(nth(expr, body_start), env) if sx_truthy((body_count == 1)) else join('', filter(lambda r: (not sx_truthy(is_spread(r))), map(lambda i: render_to_html(nth(expr, i), env), range(body_start, (body_start + body_count))))))
|
||||
result = (render_to_html(nth(expr, body_start), env) if sx_truthy((body_count == 1)) else join('', map(lambda i: render_to_html(nth(expr, i), env), range(body_start, (body_start + body_count)))))
|
||||
provide_pop(prov_name)
|
||||
return result
|
||||
else:
|
||||
@@ -2382,12 +2377,7 @@ def render_html_component(comp, args, env):
|
||||
for p in component_params(comp):
|
||||
local[p] = (dict_get(kwargs, p) if sx_truthy(dict_has(kwargs, p)) else NIL)
|
||||
if sx_truthy(component_has_children(comp)):
|
||||
parts = []
|
||||
for c in children:
|
||||
r = render_to_html(c, env)
|
||||
if sx_truthy((not sx_truthy(is_spread(r)))):
|
||||
parts.append(r)
|
||||
local['children'] = make_raw_html(join('', parts))
|
||||
local['children'] = make_raw_html(join('', map(lambda c: render_to_html(c, env), children)))
|
||||
return render_to_html(component_body(comp), local)
|
||||
|
||||
# render-html-element
|
||||
@@ -2399,14 +2389,12 @@ def render_html_element(tag, args, env):
|
||||
if sx_truthy(is_void):
|
||||
return sx_str('<', tag, render_attrs(attrs), ' />')
|
||||
else:
|
||||
content_parts = []
|
||||
for c in children:
|
||||
result = render_to_html(c, env)
|
||||
if sx_truthy(is_spread(result)):
|
||||
merge_spread_attrs(attrs, spread_attrs(result))
|
||||
else:
|
||||
content_parts.append(result)
|
||||
return sx_str('<', tag, render_attrs(attrs), '>', join('', content_parts), '</', tag, '>')
|
||||
provide_push('element-attrs', NIL)
|
||||
content = join('', map(lambda c: render_to_html(c, env), children))
|
||||
for spread_dict in sx_emitted('element-attrs'):
|
||||
merge_spread_attrs(attrs, spread_dict)
|
||||
provide_pop('element-attrs')
|
||||
return sx_str('<', tag, render_attrs(attrs), '>', content, '</', tag, '>')
|
||||
|
||||
# render-html-lake
|
||||
def render_html_lake(args, env):
|
||||
@@ -2416,14 +2404,12 @@ def render_html_lake(args, env):
|
||||
children = []
|
||||
reduce(lambda state, arg: (lambda skip: (assoc(state, 'skip', False, 'i', (get(state, 'i') + 1)) if sx_truthy(skip) else ((lambda kname: (lambda kval: _sx_begin((_sx_cell_set(_cells, 'lake_id', kval) if sx_truthy((kname == 'id')) else (_sx_cell_set(_cells, 'lake_tag', kval) if sx_truthy((kname == 'tag')) else NIL)), assoc(state, 'skip', True, 'i', (get(state, 'i') + 1))))(trampoline(eval_expr(nth(args, (get(state, 'i') + 1)), env))))(keyword_name(arg)) 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)
|
||||
lake_attrs = {'data-sx-lake': (_cells['lake_id'] if sx_truthy(_cells['lake_id']) else '')}
|
||||
content_parts = []
|
||||
for c in children:
|
||||
result = render_to_html(c, env)
|
||||
if sx_truthy(is_spread(result)):
|
||||
merge_spread_attrs(lake_attrs, spread_attrs(result))
|
||||
else:
|
||||
content_parts.append(result)
|
||||
return sx_str('<', _cells['lake_tag'], render_attrs(lake_attrs), '>', join('', content_parts), '</', _cells['lake_tag'], '>')
|
||||
provide_push('element-attrs', NIL)
|
||||
content = join('', map(lambda c: render_to_html(c, env), children))
|
||||
for spread_dict in sx_emitted('element-attrs'):
|
||||
merge_spread_attrs(lake_attrs, spread_dict)
|
||||
provide_pop('element-attrs')
|
||||
return sx_str('<', _cells['lake_tag'], render_attrs(lake_attrs), '>', content, '</', _cells['lake_tag'], '>')
|
||||
|
||||
# render-html-marsh
|
||||
def render_html_marsh(args, env):
|
||||
@@ -2433,14 +2419,12 @@ def render_html_marsh(args, env):
|
||||
children = []
|
||||
reduce(lambda state, arg: (lambda skip: (assoc(state, 'skip', False, 'i', (get(state, 'i') + 1)) if sx_truthy(skip) else ((lambda kname: (lambda kval: _sx_begin((_sx_cell_set(_cells, 'marsh_id', kval) if sx_truthy((kname == 'id')) else (_sx_cell_set(_cells, 'marsh_tag', kval) if sx_truthy((kname == 'tag')) else (NIL if sx_truthy((kname == 'transform')) else NIL))), assoc(state, 'skip', True, 'i', (get(state, 'i') + 1))))(trampoline(eval_expr(nth(args, (get(state, 'i') + 1)), env))))(keyword_name(arg)) 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)
|
||||
marsh_attrs = {'data-sx-marsh': (_cells['marsh_id'] if sx_truthy(_cells['marsh_id']) else '')}
|
||||
content_parts = []
|
||||
for c in children:
|
||||
result = render_to_html(c, env)
|
||||
if sx_truthy(is_spread(result)):
|
||||
merge_spread_attrs(marsh_attrs, spread_attrs(result))
|
||||
else:
|
||||
content_parts.append(result)
|
||||
return sx_str('<', _cells['marsh_tag'], render_attrs(marsh_attrs), '>', join('', content_parts), '</', _cells['marsh_tag'], '>')
|
||||
provide_push('element-attrs', NIL)
|
||||
content = join('', map(lambda c: render_to_html(c, env), children))
|
||||
for spread_dict in sx_emitted('element-attrs'):
|
||||
merge_spread_attrs(marsh_attrs, spread_dict)
|
||||
provide_pop('element-attrs')
|
||||
return sx_str('<', _cells['marsh_tag'], render_attrs(marsh_attrs), '>', content, '</', _cells['marsh_tag'], '>')
|
||||
|
||||
# render-html-island
|
||||
def render_html_island(island, args, env):
|
||||
@@ -2452,12 +2436,7 @@ def render_html_island(island, args, env):
|
||||
for p in component_params(island):
|
||||
local[p] = (dict_get(kwargs, p) if sx_truthy(dict_has(kwargs, p)) else NIL)
|
||||
if sx_truthy(component_has_children(island)):
|
||||
parts = []
|
||||
for c in children:
|
||||
r = render_to_html(c, env)
|
||||
if sx_truthy((not sx_truthy(is_spread(r)))):
|
||||
parts.append(r)
|
||||
local['children'] = make_raw_html(join('', parts))
|
||||
local['children'] = make_raw_html(join('', map(lambda c: render_to_html(c, env), children)))
|
||||
body_html = render_to_html(component_body(island), local)
|
||||
state_sx = serialize_island_state(kwargs)
|
||||
return sx_str('<span data-sx-island="', escape_attr(island_name), '"', (sx_str(' data-sx-state="', escape_attr(state_sx), '"') if sx_truthy(state_sx) else ''), '>', body_html, '</span>')
|
||||
@@ -2483,40 +2462,12 @@ def render_to_sx(expr, env):
|
||||
# aser
|
||||
def aser(expr, env):
|
||||
set_render_active_b(True)
|
||||
_match = type_of(expr)
|
||||
if _match == 'number':
|
||||
return expr
|
||||
elif _match == 'string':
|
||||
return expr
|
||||
elif _match == 'boolean':
|
||||
return expr
|
||||
elif _match == 'nil':
|
||||
result = _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))), ('spread', lambda: _sx_begin(sx_emit('element-attrs', spread_attrs(expr)), NIL)), (None, lambda: expr)])
|
||||
if sx_truthy(is_spread(result)):
|
||||
sx_emit('element-attrs', spread_attrs(result))
|
||||
return NIL
|
||||
elif _match == 'symbol':
|
||||
name = symbol_name(expr)
|
||||
if sx_truthy(env_has(env, name)):
|
||||
return env_get(env, name)
|
||||
elif sx_truthy(is_primitive(name)):
|
||||
return get_primitive(name)
|
||||
elif sx_truthy((name == 'true')):
|
||||
return True
|
||||
elif sx_truthy((name == 'false')):
|
||||
return False
|
||||
elif sx_truthy((name == 'nil')):
|
||||
return NIL
|
||||
else:
|
||||
return error(sx_str('Undefined symbol: ', name))
|
||||
elif _match == 'keyword':
|
||||
return keyword_name(expr)
|
||||
elif _match == 'list':
|
||||
if sx_truthy(empty_p(expr)):
|
||||
return []
|
||||
else:
|
||||
return aser_list(expr, env)
|
||||
elif _match == 'spread':
|
||||
return expr
|
||||
else:
|
||||
return expr
|
||||
return result
|
||||
|
||||
# aser-list
|
||||
def aser_list(expr, env):
|
||||
@@ -2561,10 +2512,10 @@ def aser_fragment(children, env):
|
||||
result = aser(c, env)
|
||||
if sx_truthy((type_of(result) == 'list')):
|
||||
for item in result:
|
||||
if sx_truthy(((not sx_truthy(is_nil(item))) if not sx_truthy((not sx_truthy(is_nil(item)))) else (not sx_truthy(is_spread(item))))):
|
||||
if sx_truthy((not sx_truthy(is_nil(item)))):
|
||||
parts.append(serialize(item))
|
||||
else:
|
||||
if sx_truthy(((not sx_truthy(is_nil(result))) if not sx_truthy((not sx_truthy(is_nil(result)))) else (not sx_truthy(is_spread(result))))):
|
||||
if sx_truthy((not sx_truthy(is_nil(result)))):
|
||||
parts.append(serialize(result))
|
||||
if sx_truthy(empty_p(parts)):
|
||||
return ''
|
||||
@@ -2574,9 +2525,11 @@ def aser_fragment(children, env):
|
||||
# aser-call
|
||||
def aser_call(name, args, env):
|
||||
_cells = {}
|
||||
parts = [name]
|
||||
attr_parts = []
|
||||
child_parts = []
|
||||
_cells['skip'] = False
|
||||
_cells['i'] = 0
|
||||
provide_push('element-attrs', NIL)
|
||||
for arg in args:
|
||||
if sx_truthy(_cells['skip']):
|
||||
_cells['skip'] = False
|
||||
@@ -2585,26 +2538,27 @@ def aser_call(name, args, env):
|
||||
if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((_cells['i'] + 1) < len(args)))):
|
||||
val = aser(nth(args, (_cells['i'] + 1)), env)
|
||||
if sx_truthy((not sx_truthy(is_nil(val)))):
|
||||
parts.append(sx_str(':', keyword_name(arg)))
|
||||
parts.append(serialize(val))
|
||||
attr_parts.append(sx_str(':', keyword_name(arg)))
|
||||
attr_parts.append(serialize(val))
|
||||
_cells['skip'] = True
|
||||
_cells['i'] = (_cells['i'] + 1)
|
||||
else:
|
||||
val = aser(arg, env)
|
||||
if sx_truthy((not sx_truthy(is_nil(val)))):
|
||||
if sx_truthy(is_spread(val)):
|
||||
for k in keys(spread_attrs(val)):
|
||||
v = dict_get(spread_attrs(val), k)
|
||||
parts.append(sx_str(':', k))
|
||||
parts.append(serialize(v))
|
||||
if sx_truthy((type_of(val) == 'list')):
|
||||
for item in val:
|
||||
if sx_truthy((not sx_truthy(is_nil(item)))):
|
||||
child_parts.append(serialize(item))
|
||||
else:
|
||||
if sx_truthy((type_of(val) == 'list')):
|
||||
for item in val:
|
||||
if sx_truthy((not sx_truthy(is_nil(item)))):
|
||||
parts.append(serialize(item))
|
||||
else:
|
||||
parts.append(serialize(val))
|
||||
child_parts.append(serialize(val))
|
||||
_cells['i'] = (_cells['i'] + 1)
|
||||
for spread_dict in sx_emitted('element-attrs'):
|
||||
for k in keys(spread_dict):
|
||||
v = dict_get(spread_dict, k)
|
||||
attr_parts.append(sx_str(':', k))
|
||||
attr_parts.append(serialize(v))
|
||||
provide_pop('element-attrs')
|
||||
parts = concat([name], attr_parts, child_parts)
|
||||
return sx_str('(', join(' ', parts), ')')
|
||||
|
||||
# SPECIAL_FORM_NAMES
|
||||
@@ -3659,7 +3613,8 @@ async def async_render(expr, env, ctx):
|
||||
elif _match == 'raw-html':
|
||||
return raw_html_content(expr)
|
||||
elif _match == 'spread':
|
||||
return expr
|
||||
sx_emit('element-attrs', spread_attrs(expr))
|
||||
return ''
|
||||
elif _match == 'symbol':
|
||||
val = (await async_eval(expr, env, ctx))
|
||||
return (await async_render(val, env, ctx))
|
||||
@@ -3691,7 +3646,7 @@ async def async_render_list(expr, env, ctx):
|
||||
elif sx_truthy((name == 'raw!')):
|
||||
return (await async_render_raw(args, env, ctx))
|
||||
elif sx_truthy((name == '<>')):
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), (await async_map_render(args, env, ctx))))
|
||||
return join('', (await async_map_render(args, env, ctx)))
|
||||
elif sx_truthy(starts_with_p(name, 'html:')):
|
||||
return (await async_render_element(slice(name, 5), args, env, ctx))
|
||||
elif sx_truthy(async_render_form_p(name)):
|
||||
@@ -3746,12 +3701,12 @@ async def async_render_element(tag, args, env, ctx):
|
||||
else:
|
||||
token = (svg_context_set(True) if sx_truthy(((tag == 'svg') if sx_truthy((tag == 'svg')) else (tag == 'math'))) else NIL)
|
||||
content_parts = []
|
||||
provide_push('element-attrs', NIL)
|
||||
for c in children:
|
||||
result = (await async_render(c, env, ctx))
|
||||
if sx_truthy(is_spread(result)):
|
||||
merge_spread_attrs(attrs, spread_attrs(result))
|
||||
else:
|
||||
content_parts.append(result)
|
||||
content_parts.append((await async_render(c, env, ctx)))
|
||||
for spread_dict in sx_emitted('element-attrs'):
|
||||
merge_spread_attrs(attrs, spread_dict)
|
||||
provide_pop('element-attrs')
|
||||
if sx_truthy(token):
|
||||
svg_context_reset(token)
|
||||
return sx_str('<', tag, render_attrs(attrs), '>', join('', content_parts), '</', tag, '>')
|
||||
@@ -3787,9 +3742,7 @@ async def async_render_component(comp, args, env, ctx):
|
||||
if sx_truthy(component_has_children(comp)):
|
||||
parts = []
|
||||
for c in children:
|
||||
r = (await async_render(c, env, ctx))
|
||||
if sx_truthy((not sx_truthy(is_spread(r)))):
|
||||
parts.append(r)
|
||||
parts.append((await async_render(c, env, ctx)))
|
||||
local['children'] = make_raw_html(join('', parts))
|
||||
return (await async_render(component_body(comp), local, ctx))
|
||||
|
||||
@@ -3805,9 +3758,7 @@ async def async_render_island(island, args, env, ctx):
|
||||
if sx_truthy(component_has_children(island)):
|
||||
parts = []
|
||||
for c in children:
|
||||
r = (await async_render(c, env, ctx))
|
||||
if sx_truthy((not sx_truthy(is_spread(r)))):
|
||||
parts.append(r)
|
||||
parts.append((await async_render(c, env, ctx)))
|
||||
local['children'] = make_raw_html(join('', parts))
|
||||
body_html = (await async_render(component_body(island), local, ctx))
|
||||
state_json = serialize_island_state(kwargs)
|
||||
@@ -3871,8 +3822,7 @@ async def dispatch_async_render_form(name, expr, env, ctx):
|
||||
if sx_truthy((len(expr) == 3)):
|
||||
return (await async_render(nth(expr, 2), env, ctx))
|
||||
else:
|
||||
results = (await async_map_render(slice(expr, 2), env, ctx))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), results))
|
||||
return join('', (await async_map_render(slice(expr, 2), env, ctx)))
|
||||
elif sx_truthy((name == 'cond')):
|
||||
clauses = rest(expr)
|
||||
if sx_truthy(cond_scheme_p(clauses)):
|
||||
@@ -3886,38 +3836,36 @@ async def dispatch_async_render_form(name, expr, env, ctx):
|
||||
if sx_truthy((len(expr) == 3)):
|
||||
return (await async_render(nth(expr, 2), local, ctx))
|
||||
else:
|
||||
results = (await async_map_render(slice(expr, 2), local, ctx))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), results))
|
||||
return join('', (await async_map_render(slice(expr, 2), local, ctx)))
|
||||
elif sx_truthy(((name == 'begin') if sx_truthy((name == 'begin')) else (name == 'do'))):
|
||||
if sx_truthy((len(expr) == 2)):
|
||||
return (await async_render(nth(expr, 1), env, ctx))
|
||||
else:
|
||||
results = (await async_map_render(rest(expr), env, ctx))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), results))
|
||||
return join('', (await async_map_render(rest(expr), env, ctx)))
|
||||
elif sx_truthy(is_definition_form(name)):
|
||||
(await async_eval(expr, env, ctx))
|
||||
return ''
|
||||
elif sx_truthy((name == 'map')):
|
||||
f = (await async_eval(nth(expr, 1), env, ctx))
|
||||
coll = (await async_eval(nth(expr, 2), env, ctx))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), (await async_map_fn_render(f, coll, env, ctx))))
|
||||
return join('', (await async_map_fn_render(f, coll, env, ctx)))
|
||||
elif sx_truthy((name == 'map-indexed')):
|
||||
f = (await async_eval(nth(expr, 1), env, ctx))
|
||||
coll = (await async_eval(nth(expr, 2), env, ctx))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), (await async_map_indexed_fn_render(f, coll, env, ctx))))
|
||||
return join('', (await async_map_indexed_fn_render(f, coll, env, ctx)))
|
||||
elif sx_truthy((name == 'filter')):
|
||||
return (await async_render((await async_eval(expr, env, ctx)), env, ctx))
|
||||
elif sx_truthy((name == 'for-each')):
|
||||
f = (await async_eval(nth(expr, 1), env, ctx))
|
||||
coll = (await async_eval(nth(expr, 2), env, ctx))
|
||||
return join('', filter(lambda r: (not sx_truthy(is_spread(r))), (await async_map_fn_render(f, coll, env, ctx))))
|
||||
return join('', (await async_map_fn_render(f, coll, env, ctx)))
|
||||
elif sx_truthy((name == 'provide')):
|
||||
prov_name = (await async_eval(nth(expr, 1), env, ctx))
|
||||
prov_val = (await async_eval(nth(expr, 2), env, ctx))
|
||||
body_start = 3
|
||||
body_count = (len(expr) - 3)
|
||||
provide_push(prov_name, prov_val)
|
||||
result = ((await async_render(nth(expr, body_start), env, ctx)) if sx_truthy((body_count == 1)) else (lambda results: join('', filter(lambda r: (not sx_truthy(is_spread(r))), results)))((await async_map_render(slice(expr, body_start), env, ctx))))
|
||||
result = ((await async_render(nth(expr, body_start), env, ctx)) if sx_truthy((body_count == 1)) else join('', (await async_map_render(slice(expr, body_start), env, ctx))))
|
||||
provide_pop(prov_name)
|
||||
return result
|
||||
else:
|
||||
@@ -4019,42 +3967,35 @@ async def async_invoke(f, *args):
|
||||
|
||||
# async-aser
|
||||
async def async_aser(expr, env, ctx):
|
||||
_match = type_of(expr)
|
||||
if _match == 'number':
|
||||
return expr
|
||||
elif _match == 'string':
|
||||
return expr
|
||||
elif _match == 'boolean':
|
||||
return expr
|
||||
elif _match == 'nil':
|
||||
return NIL
|
||||
elif _match == 'symbol':
|
||||
t = type_of(expr)
|
||||
result = NIL
|
||||
if sx_truthy((t == 'number')):
|
||||
result = expr
|
||||
elif sx_truthy((t == 'string')):
|
||||
result = expr
|
||||
elif sx_truthy((t == 'boolean')):
|
||||
result = expr
|
||||
elif sx_truthy((t == 'nil')):
|
||||
result = NIL
|
||||
elif sx_truthy((t == 'symbol')):
|
||||
name = symbol_name(expr)
|
||||
if sx_truthy(env_has(env, name)):
|
||||
return env_get(env, name)
|
||||
elif sx_truthy(is_primitive(name)):
|
||||
return get_primitive(name)
|
||||
elif sx_truthy((name == 'true')):
|
||||
return True
|
||||
elif sx_truthy((name == 'false')):
|
||||
return False
|
||||
elif sx_truthy((name == 'nil')):
|
||||
return NIL
|
||||
else:
|
||||
return error(sx_str('Undefined symbol: ', name))
|
||||
elif _match == 'keyword':
|
||||
return keyword_name(expr)
|
||||
elif _match == 'dict':
|
||||
return (await async_aser_dict(expr, env, ctx))
|
||||
elif _match == 'spread':
|
||||
return expr
|
||||
elif _match == 'list':
|
||||
if sx_truthy(empty_p(expr)):
|
||||
return []
|
||||
else:
|
||||
return (await async_aser_list(expr, env, ctx))
|
||||
result = (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)))))))
|
||||
elif sx_truthy((t == 'keyword')):
|
||||
result = keyword_name(expr)
|
||||
elif sx_truthy((t == 'dict')):
|
||||
result = (await async_aser_dict(expr, env, ctx))
|
||||
elif sx_truthy((t == 'spread')):
|
||||
sx_emit('element-attrs', spread_attrs(expr))
|
||||
result = NIL
|
||||
elif sx_truthy((t == 'list')):
|
||||
result = ([] if sx_truthy(empty_p(expr)) else (await async_aser_list(expr, env, ctx)))
|
||||
else:
|
||||
return expr
|
||||
result = expr
|
||||
if sx_truthy(is_spread(result)):
|
||||
sx_emit('element-attrs', spread_attrs(result))
|
||||
return NIL
|
||||
else:
|
||||
return result
|
||||
|
||||
# async-aser-dict
|
||||
async def async_aser_dict(expr, env, ctx):
|
||||
@@ -4148,10 +4089,10 @@ async def async_aser_fragment(children, env, ctx):
|
||||
result = (await async_aser(c, env, ctx))
|
||||
if sx_truthy((type_of(result) == 'list')):
|
||||
for item in result:
|
||||
if sx_truthy(((not sx_truthy(is_nil(item))) if not sx_truthy((not sx_truthy(is_nil(item)))) else (not sx_truthy(is_spread(item))))):
|
||||
if sx_truthy((not sx_truthy(is_nil(item)))):
|
||||
parts.append(serialize(item))
|
||||
else:
|
||||
if sx_truthy(((not sx_truthy(is_nil(result))) if not sx_truthy((not sx_truthy(is_nil(result)))) else (not sx_truthy(is_spread(result))))):
|
||||
if sx_truthy((not sx_truthy(is_nil(result)))):
|
||||
parts.append(serialize(result))
|
||||
if sx_truthy(empty_p(parts)):
|
||||
return make_sx_expr('')
|
||||
@@ -4204,9 +4145,11 @@ async def async_parse_aser_kw_args(args, kwargs, children, env, ctx):
|
||||
async def async_aser_call(name, args, env, ctx):
|
||||
_cells = {}
|
||||
token = (svg_context_set(True) if sx_truthy(((name == 'svg') if sx_truthy((name == 'svg')) else (name == 'math'))) else NIL)
|
||||
parts = [name]
|
||||
attr_parts = []
|
||||
child_parts = []
|
||||
_cells['skip'] = False
|
||||
_cells['i'] = 0
|
||||
provide_push('element-attrs', NIL)
|
||||
for arg in args:
|
||||
if sx_truthy(_cells['skip']):
|
||||
_cells['skip'] = False
|
||||
@@ -4215,39 +4158,40 @@ async def async_aser_call(name, args, env, ctx):
|
||||
if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((_cells['i'] + 1) < len(args)))):
|
||||
val = (await async_aser(nth(args, (_cells['i'] + 1)), env, ctx))
|
||||
if sx_truthy((not sx_truthy(is_nil(val)))):
|
||||
parts.append(sx_str(':', keyword_name(arg)))
|
||||
attr_parts.append(sx_str(':', keyword_name(arg)))
|
||||
if sx_truthy((type_of(val) == 'list')):
|
||||
live = filter(lambda v: (not sx_truthy(is_nil(v))), val)
|
||||
if sx_truthy(empty_p(live)):
|
||||
parts.append('nil')
|
||||
attr_parts.append('nil')
|
||||
else:
|
||||
items = map(serialize, live)
|
||||
if sx_truthy(some(lambda v: is_sx_expr(v), live)):
|
||||
parts.append(sx_str('(<> ', join(' ', items), ')'))
|
||||
attr_parts.append(sx_str('(<> ', join(' ', items), ')'))
|
||||
else:
|
||||
parts.append(sx_str('(list ', join(' ', items), ')'))
|
||||
attr_parts.append(sx_str('(list ', join(' ', items), ')'))
|
||||
else:
|
||||
parts.append(serialize(val))
|
||||
attr_parts.append(serialize(val))
|
||||
_cells['skip'] = True
|
||||
_cells['i'] = (_cells['i'] + 1)
|
||||
else:
|
||||
result = (await async_aser(arg, env, ctx))
|
||||
if sx_truthy((not sx_truthy(is_nil(result)))):
|
||||
if sx_truthy(is_spread(result)):
|
||||
for k in keys(spread_attrs(result)):
|
||||
v = dict_get(spread_attrs(result), k)
|
||||
parts.append(sx_str(':', k))
|
||||
parts.append(serialize(v))
|
||||
if sx_truthy((type_of(result) == 'list')):
|
||||
for item in result:
|
||||
if sx_truthy((not sx_truthy(is_nil(item)))):
|
||||
child_parts.append(serialize(item))
|
||||
else:
|
||||
if sx_truthy((type_of(result) == 'list')):
|
||||
for item in result:
|
||||
if sx_truthy((not sx_truthy(is_nil(item)))):
|
||||
parts.append(serialize(item))
|
||||
else:
|
||||
parts.append(serialize(result))
|
||||
child_parts.append(serialize(result))
|
||||
_cells['i'] = (_cells['i'] + 1)
|
||||
for spread_dict in sx_emitted('element-attrs'):
|
||||
for k in keys(spread_dict):
|
||||
v = dict_get(spread_dict, k)
|
||||
attr_parts.append(sx_str(':', k))
|
||||
attr_parts.append(serialize(v))
|
||||
provide_pop('element-attrs')
|
||||
if sx_truthy(token):
|
||||
svg_context_reset(token)
|
||||
parts = concat([name], attr_parts, child_parts)
|
||||
return make_sx_expr(sx_str('(', join(' ', parts), ')'))
|
||||
|
||||
# ASYNC_ASER_FORM_NAMES
|
||||
|
||||
Reference in New Issue
Block a user