Spec server definition forms (defhandler/defquery/defaction/defpage) in forms.sx

Previously defhandler routed to sf-define which tried to evaluate
(&key ...) params as expressions. Now each form has its own spec
with parse-key-params and platform constructors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 22:36:56 +00:00
parent 5aa13a99d1
commit d076fc1465
5 changed files with 283 additions and 2 deletions

View File

@@ -106,6 +106,10 @@ class PyEmitter:
"make-component": "make_component",
"make-macro": "make_macro",
"make-thunk": "make_thunk",
"make-handler-def": "make_handler_def",
"make-query-def": "make_query_def",
"make-action-def": "make_action_def",
"make-page-def": "make_page_def",
"make-symbol": "make_symbol",
"make-keyword": "make_keyword",
"lambda-params": "lambda_params",
@@ -821,6 +825,7 @@ def compile_ref_to_py(adapters: list[str] | None = None) -> str:
# Core files always included, then selected adapters
sx_files = [
("eval.sx", "eval"),
("forms.sx", "forms (server definition forms)"),
("render.sx", "render (core)"),
]
for name in ("html", "sx"):
@@ -883,6 +888,7 @@ from typing import Any
from shared.sx.types import (
NIL, Symbol, Keyword, Lambda, Component, Macro, StyleValue,
HandlerDef, QueryDef, ActionDef, PageDef,
)
from shared.sx.parser import SxExpr
'''
@@ -1029,6 +1035,39 @@ def make_macro(params, rest_param, body, env, name=None):
closure=dict(env), name=name)
def make_handler_def(name, params, body, env):
return HandlerDef(name=name, params=list(params), body=body, closure=dict(env))
def make_query_def(name, params, doc, body, env):
return QueryDef(name=name, params=list(params), doc=doc, body=body, closure=dict(env))
def make_action_def(name, params, doc, body, env):
return ActionDef(name=name, params=list(params), doc=doc, body=body, closure=dict(env))
def make_page_def(name, slots, env):
path = slots.get("path", "")
auth_val = slots.get("auth", "public")
if isinstance(auth_val, Keyword):
auth = auth_val.name
elif isinstance(auth_val, list):
auth = [item.name if isinstance(item, Keyword) else str(item) for item in auth_val]
else:
auth = str(auth_val) if auth_val else "public"
layout = slots.get("layout")
if isinstance(layout, Keyword):
layout = layout.name
cache = None
return PageDef(
name=name, path=path, auth=auth, layout=layout, cache=cache,
data_expr=slots.get("data"), content_expr=slots.get("content"),
filter_expr=slots.get("filter"), aside_expr=slots.get("aside"),
menu_expr=slots.get("menu"), closure=dict(env),
)
def make_thunk(expr, env):
return _Thunk(expr, env)