Implement js.sx: self-hosting SX-to-JavaScript bootstrapper

SX-to-JavaScript translator written in SX itself. When executed by the
Python evaluator against the spec files, produces output identical to
the hand-written bootstrap_js.py JSEmitter.

- 1,382 lines, 61 defines
- 431/431 defines match across all 22 spec files (G0 == G1)
- 267 defines in the standard compilation, 151,763 bytes identical
- camelCase mangling, var declarations, function(){} syntax
- Self-tail-recursive optimization (zero-arg → while loops)
- JS-native statement patterns: d[k]=v, arr.push(x), f.name=x

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 01:36:12 +00:00
parent fd4f13e571
commit e6ca1a5f44
2 changed files with 1483 additions and 0 deletions

1382
shared/sx/ref/js.sx Normal file

File diff suppressed because it is too large Load Diff

101
shared/sx/ref/run_js_sx.py Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env python3
"""
Bootstrap runner: execute js.sx against spec files to produce sx-ref.js.
This is the G1 bootstrapper — js.sx (SX-to-JavaScript translator written in SX)
is loaded into the Python evaluator, which then uses it to translate the
spec .sx files into JavaScript.
The output (transpiled defines only) should be identical to what
bootstrap_js.py's JSEmitter produces.
Usage:
python run_js_sx.py > /tmp/sx_ref_g1.js
"""
from __future__ import annotations
import os
import sys
_HERE = os.path.dirname(os.path.abspath(__file__))
_PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..", ".."))
sys.path.insert(0, _PROJECT)
from shared.sx.parser import parse_all
from shared.sx.types import Symbol
def load_js_sx() -> dict:
"""Load js.sx into an evaluator environment and return it."""
js_sx_path = os.path.join(_HERE, "js.sx")
with open(js_sx_path) as f:
source = f.read()
exprs = parse_all(source)
from shared.sx.evaluator import evaluate, make_env
env = make_env()
for expr in exprs:
evaluate(expr, env)
return env
def extract_defines(source: str) -> list[tuple[str, list]]:
"""Parse .sx source, return list of (name, define-expr) for top-level defines."""
exprs = parse_all(source)
defines = []
for expr in exprs:
if isinstance(expr, list) and expr and isinstance(expr[0], Symbol):
if expr[0].name == "define":
name = expr[1].name if isinstance(expr[1], Symbol) else str(expr[1])
defines.append((name, expr))
return defines
def main():
from shared.sx.evaluator import evaluate
# Load js.sx into evaluator
env = load_js_sx()
# Same file list and order as bootstrap_js.py compile_ref_to_js() with all adapters
sx_files = [
("eval.sx", "eval"),
("render.sx", "render (core)"),
("parser.sx", "parser"),
("adapter-html.sx", "adapter-html"),
("adapter-sx.sx", "adapter-sx"),
("adapter-dom.sx", "adapter-dom"),
("engine.sx", "engine"),
("orchestration.sx", "orchestration"),
("boot.sx", "boot"),
("deps.sx", "deps (component dependency analysis)"),
("router.sx", "router (client-side route matching)"),
("signals.sx", "signals (reactive signal runtime)"),
]
# Translate each spec file using js.sx
for filename, label in sx_files:
filepath = os.path.join(_HERE, filename)
if not os.path.exists(filepath):
continue
with open(filepath) as f:
src = f.read()
defines = extract_defines(src)
# Convert defines to SX-compatible format
sx_defines = [[name, expr] for name, expr in defines]
print(f"\n // === Transpiled from {label} ===\n")
env["_defines"] = sx_defines
result = evaluate(
[Symbol("js-translate-file"), Symbol("_defines")],
env,
)
print(result)
if __name__ == "__main__":
main()