Decouple core evaluator from web platform, extract libraries

The core evaluator (spec/evaluator.sx) is now the irreducible computational
core with zero web, rendering, or type-system knowledge. 2531 → 2313 lines.

- Add extensible special form registry (*custom-special-forms* + register-special-form!)
- Add render dispatch hooks (*render-check* / *render-fn*) replacing hardcoded render-active?/is-render-expr?/render-expr
- Extract freeze scopes → spec/freeze.sx (library, not core)
- Extract content addressing → spec/content.sx (library, not core)
- Move sf-deftype/sf-defeffect → spec/types.sx (self-registering)
- Move sf-defstyle → web/forms.sx (self-registering with all web forms)
- Move web tests (defpage, streaming) → web/tests/test-forms.sx
- Add is-else-clause? helper (replaces 5 inline patterns)
- Make escape-html/escape-attr library functions in render.sx (pure SX, not platform-provided)
- Add foundations plan: Step 3.5 (data representations), Step 3.7 (verified components), OCaml for Step 4d
- Update all three bootstrappers (JS 957/957, Python 744/744, OCaml 952/952)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-16 08:37:50 +00:00
parent 5ab3ecb7e0
commit 06666ac8c4
21 changed files with 886 additions and 603 deletions

View File

@@ -612,13 +612,7 @@ def inspect(x):
return repr(x)
def escape_html(s):
s = str(s)
return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;")
def escape_attr(s):
return escape_html(s)
# escape_html and escape_attr are now library functions defined in render.sx
def raw_html_content(x):
@@ -842,7 +836,7 @@ def _sx_parse_int(v, default=0):
"stdlib.text": '''
# stdlib.text
PRIMITIVES["pluralize"] = lambda n, s="", p="s": s if n == 1 else p
PRIMITIVES["escape"] = escape_html
PRIMITIVES["escape"] = lambda s: str(s).replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;")
PRIMITIVES["strip-tags"] = lambda s: _strip_tags(str(s))
import re as _re
@@ -1647,12 +1641,15 @@ SPEC_MODULES = {
"signals": ("signals.sx", "signals (reactive signal runtime)"),
"page-helpers": ("page-helpers.sx", "page-helpers (pure data transformation helpers)"),
"types": ("types.sx", "types (gradual type system)"),
"freeze": ("freeze.sx", "freeze (serializable state boundaries)"),
"content": ("content.sx", "content (content-addressed computation)"),
}
# Note: frames and cek are now part of evaluator.sx (always loaded as core)
# Explicit ordering for spec modules with dependencies.
# freeze depends on signals; content depends on freeze.
SPEC_MODULE_ORDER = [
"deps", "engine", "page-helpers", "router", "signals", "types",
"deps", "engine", "page-helpers", "router", "signals", "types", "freeze", "content",
]
EXTENSION_NAMES = {"continuations"}