Add live self-hosting bootstrapper page to bootstrappers section
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m15s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m15s
- Update plan page with completion status and results - Add ~bootstrapper-self-hosting-content component with live G0/G1 verification - Add _self_hosting_data() helper: loads py.sx, runs it, diffs against G0 - Add "Self-Hosting (py.sx)" to bootstrappers nav and index table - Wire /bootstrappers/self-hosting route Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -448,13 +448,25 @@
|
||||
:data (bootstrapper-data slug)
|
||||
:content (if bootstrapper-not-found
|
||||
(~spec-not-found :slug slug)
|
||||
(if (= slug "python")
|
||||
(~bootstrapper-py-content
|
||||
:bootstrapper-source bootstrapper-source
|
||||
:bootstrapped-output bootstrapped-output)
|
||||
(~bootstrapper-js-content
|
||||
:bootstrapper-source bootstrapper-source
|
||||
:bootstrapped-output bootstrapped-output))))
|
||||
(case slug
|
||||
"self-hosting"
|
||||
(~bootstrapper-self-hosting-content
|
||||
:py-sx-source py-sx-source
|
||||
:g0-output g0-output
|
||||
:g1-output g1-output
|
||||
:defines-matched defines-matched
|
||||
:defines-total defines-total
|
||||
:g0-lines g0-lines
|
||||
:g0-bytes g0-bytes
|
||||
:verification-status verification-status)
|
||||
"python"
|
||||
(~bootstrapper-py-content
|
||||
:bootstrapper-source bootstrapper-source
|
||||
:bootstrapped-output bootstrapped-output)
|
||||
:else
|
||||
(~bootstrapper-js-content
|
||||
:bootstrapper-source bootstrapper-source
|
||||
:bootstrapped-output bootstrapped-output))))
|
||||
|
||||
;; ---------------------------------------------------------------------------
|
||||
;; Isomorphism section
|
||||
|
||||
@@ -230,9 +230,12 @@ def _bootstrapper_data(target: str) -> dict:
|
||||
"""
|
||||
import os
|
||||
|
||||
if target not in ("javascript", "python"):
|
||||
if target not in ("javascript", "python", "self-hosting"):
|
||||
return {"bootstrapper-not-found": True}
|
||||
|
||||
if target == "self-hosting":
|
||||
return _self_hosting_data(ref_dir)
|
||||
|
||||
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
|
||||
if not os.path.isdir(ref_dir):
|
||||
ref_dir = "/app/shared/sx/ref"
|
||||
@@ -276,6 +279,80 @@ def _bootstrapper_data(target: str) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _self_hosting_data(ref_dir: str) -> dict:
|
||||
"""Run py.sx live: load into evaluator, translate spec files, diff against G0."""
|
||||
import os
|
||||
from shared.sx.parser import parse_all
|
||||
from shared.sx.types import Symbol
|
||||
from shared.sx.evaluator import evaluate, make_env
|
||||
from shared.sx.ref.bootstrap_py import extract_defines, compile_ref_to_py, PyEmitter
|
||||
|
||||
try:
|
||||
# Read py.sx source
|
||||
py_sx_path = os.path.join(ref_dir, "py.sx")
|
||||
with open(py_sx_path, encoding="utf-8") as f:
|
||||
py_sx_source = f.read()
|
||||
|
||||
# Load py.sx into evaluator
|
||||
exprs = parse_all(py_sx_source)
|
||||
env = make_env()
|
||||
for expr in exprs:
|
||||
evaluate(expr, env)
|
||||
|
||||
# Generate G0 (hand-written bootstrapper)
|
||||
g0_output = compile_ref_to_py()
|
||||
|
||||
# Generate G1 (py.sx) — translate each spec file
|
||||
sx_files = [
|
||||
("eval.sx", "eval"), ("forms.sx", "forms (server definition forms)"),
|
||||
("render.sx", "render (core)"),
|
||||
("adapter-html.sx", "adapter-html"), ("adapter-sx.sx", "adapter-sx"),
|
||||
("deps.sx", "deps (component dependency analysis)"),
|
||||
("signals.sx", "signals (reactive signal runtime)"),
|
||||
]
|
||||
emitter = PyEmitter()
|
||||
total = 0
|
||||
matched = 0
|
||||
for filename, _label in sx_files:
|
||||
filepath = os.path.join(ref_dir, filename)
|
||||
if not os.path.exists(filepath):
|
||||
continue
|
||||
with open(filepath, encoding="utf-8") as f:
|
||||
src = f.read()
|
||||
defines = extract_defines(src)
|
||||
for name, expr in defines:
|
||||
g0_stmt = emitter.emit_statement(expr)
|
||||
g1_stmt = evaluate(
|
||||
[Symbol("py-statement"), [Symbol("quote"), expr], 0], env
|
||||
)
|
||||
total += 1
|
||||
if g0_stmt == g1_stmt:
|
||||
matched += 1
|
||||
|
||||
g0_lines = len(g0_output.splitlines())
|
||||
g0_bytes = len(g0_output)
|
||||
status = "identical" if matched == total else "mismatch"
|
||||
|
||||
except Exception as e:
|
||||
py_sx_source = f";; error loading py.sx: {e}"
|
||||
g0_output = f"# error: {e}"
|
||||
matched, total = 0, 0
|
||||
g0_lines, g0_bytes = 0, 0
|
||||
status = "error"
|
||||
|
||||
return {
|
||||
"bootstrapper-not-found": None,
|
||||
"py-sx-source": py_sx_source,
|
||||
"g0-output": g0_output,
|
||||
"g1-output": g0_output if status == "identical" else "# differs from G0",
|
||||
"defines-matched": str(matched),
|
||||
"defines-total": str(total),
|
||||
"g0-lines": str(g0_lines),
|
||||
"g0-bytes": str(g0_bytes),
|
||||
"verification-status": status,
|
||||
}
|
||||
|
||||
|
||||
def _bundle_analyzer_data() -> dict:
|
||||
"""Compute per-page component bundle analysis for the sx-docs app."""
|
||||
from shared.sx.jinja_bridge import get_component_env
|
||||
|
||||
Reference in New Issue
Block a user