Separate core spec from web framework
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m49s

Three-layer architecture:
  spec/  — Core language (19 files): evaluator, parser, primitives,
           CEK machine, types, continuations. Host-independent.
  web/   — Web framework (20 files): signals, adapters, engine,
           orchestration, boot, router, CSSX. Built on core spec.
  sx/    — Application (sx-docs website). Built on web framework.

Split boundary.sx into boundary-core.sx (type-of, make-env, identical?)
and boundary-web.sx (IO primitives, signals, spreads, page helpers).

Bootstrappers search spec/ → web/ → shared/sx/ref/ for .sx files.
Original files remain in shared/sx/ref/ as fallback during transition.
All 63 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 01:42:19 +00:00
parent ab015fa2fd
commit 1a3d7b3d77
41 changed files with 20182 additions and 9 deletions

View File

@@ -1325,9 +1325,17 @@ except ImportError:
)
def _parse_special_forms_spec(ref_dir: str) -> set[str]:
def _parse_special_forms_spec(ref_dir: str, source_dirs=None) -> set[str]:
"""Parse special-forms.sx to extract declared form names."""
filepath = os.path.join(ref_dir, "special-forms.sx")
filepath = None
if source_dirs:
for d in source_dirs:
p = os.path.join(d, "special-forms.sx")
if os.path.exists(p):
filepath = p
break
if not filepath:
filepath = os.path.join(ref_dir, "special-forms.sx")
if not os.path.exists(filepath):
return set()
with open(filepath) as f:
@@ -1359,9 +1367,9 @@ def _extract_eval_dispatch_names(all_sections: list) -> set[str]:
def _validate_special_forms(ref_dir: str, all_sections: list,
has_continuations: bool) -> None:
has_continuations: bool, source_dirs=None) -> None:
"""Cross-check special-forms.sx against eval.sx dispatch. Warn on mismatches."""
spec_names = _parse_special_forms_spec(ref_dir)
spec_names = _parse_special_forms_spec(ref_dir, source_dirs=source_dirs)
if not spec_names:
return
@@ -1432,6 +1440,20 @@ def compile_ref_to_py(
prim_modules.append(m)
ref_dir = os.path.dirname(os.path.abspath(__file__))
_project = os.path.abspath(os.path.join(ref_dir, "..", "..", ".."))
_source_dirs = [
os.path.join(_project, "spec"),
os.path.join(_project, "web"),
ref_dir,
]
def _find_sx(filename):
for d in _source_dirs:
p = os.path.join(d, filename)
if os.path.exists(p):
return p
return None
emitter = PyEmitter()
# Resolve adapter set
@@ -1494,7 +1516,7 @@ def compile_ref_to_py(
has_async = "async" in adapter_set
if has_async:
async_filename = ADAPTER_FILES["async"][0]
async_filepath = os.path.join(ref_dir, async_filename)
async_filepath = _find_sx(async_filename) or os.path.join(ref_dir, async_filename)
if os.path.exists(async_filepath):
with open(async_filepath) as f:
async_src = f.read()
@@ -1513,7 +1535,7 @@ def compile_ref_to_py(
all_sections = []
for filename, label in sx_files:
filepath = os.path.join(ref_dir, filename)
filepath = _find_sx(filename) or os.path.join(ref_dir, filename)
if not os.path.exists(filepath):
continue
with open(filepath) as f:
@@ -1531,7 +1553,7 @@ def compile_ref_to_py(
has_continuations = "continuations" in ext_set
# Validate special forms
_validate_special_forms(ref_dir, all_sections, has_continuations)
_validate_special_forms(ref_dir, all_sections, has_continuations, source_dirs=_source_dirs)
# Build output
has_html = "html" in adapter_set

View File

@@ -78,6 +78,13 @@ def compile_ref_to_js(
from shared.sx.ref.sx_ref import evaluate
ref_dir = _HERE
_PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..", ".."))
# Source directories: core spec, web framework, and legacy ref (for bootstrapper tools)
_source_dirs = [
os.path.join(_PROJECT, "spec"), # Core spec
os.path.join(_PROJECT, "web"), # Web framework
ref_dir, # Legacy location (fallback)
]
env = load_js_sx()
# Resolve adapter set
@@ -195,9 +202,16 @@ def compile_ref_to_js(
parts.append(PLATFORM_CEK_JS)
# Translate each spec file using js.sx
def _find_sx(filename):
for d in _source_dirs:
p = os.path.join(d, filename)
if os.path.exists(p):
return p
return None
for filename, label in sx_files:
filepath = os.path.join(ref_dir, filename)
if not os.path.exists(filepath):
filepath = _find_sx(filename)
if not filepath:
continue
with open(filepath) as f:
src = f.read()