Self-hosted z3.sx translator, prove.sx prover, parser unicode, auto reader macros

- z3.sx: SX-to-SMT-LIB translator written in SX (359 lines), replaces Python translation logic
- prove.sx: SMT-LIB satisfiability checker in SX — proves all 91 primitives sat by construction
- Parser: support unicode characters (em-dash, accented letters) in symbols
- Auto-resolve reader macros: #name finds name-translate in component env, no Python registration
- Platform primitives: type-of, symbol-name, keyword-name, sx-parse registered in primitives.py
- Cond heuristic: predicates ending in ? recognized as Clojure-style tests
- Library loading: z3.sx loaded at startup with reload callbacks for hot-reload ordering
- reader_z3.py: rewritten as thin shell delegating to z3.sx
- Split monolithic .sx files: essays (22), plans (13), reactive-islands (6) into separate files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 22:47:53 +00:00
parent 8b1333de96
commit 3ca89ef765
53 changed files with 5970 additions and 5222 deletions

View File

@@ -98,7 +98,7 @@ def load_sx_dir(directory: str) -> None:
Skips boundary.sx — those are parsed separately by the boundary validator.
"""
for filepath in sorted(
glob.glob(os.path.join(directory, "*.sx"))
glob.glob(os.path.join(directory, "**", "*.sx"), recursive=True)
):
if os.path.basename(filepath) == "boundary.sx":
continue
@@ -112,6 +112,12 @@ def load_sx_dir(directory: str) -> None:
_watched_dirs: list[str] = []
_file_mtimes: dict[str, float] = {}
_reload_callbacks: list[Any] = []
def register_reload_callback(fn: Any) -> None:
"""Register a function to call after hot-reload clears and reloads components."""
_reload_callbacks.append(fn)
def watch_sx_dir(directory: str) -> None:
@@ -119,7 +125,7 @@ def watch_sx_dir(directory: str) -> None:
_watched_dirs.append(directory)
# Seed mtimes
for fp in sorted(
glob.glob(os.path.join(directory, "*.sx"))
glob.glob(os.path.join(directory, "**", "*.sx"), recursive=True)
):
_file_mtimes[fp] = os.path.getmtime(fp)
@@ -129,7 +135,7 @@ def reload_if_changed() -> None:
changed = False
for directory in _watched_dirs:
for fp in sorted(
glob.glob(os.path.join(directory, "*.sx"))
glob.glob(os.path.join(directory, "**", "*.sx"), recursive=True)
):
mtime = os.path.getmtime(fp)
if fp not in _file_mtimes or _file_mtimes[fp] != mtime:
@@ -137,6 +143,9 @@ def reload_if_changed() -> None:
changed = True
if changed:
_COMPONENT_ENV.clear()
# Reload SX libraries first (e.g. z3.sx) so reader macros resolve
for cb in _reload_callbacks:
cb()
for directory in _watched_dirs:
load_sx_dir(directory)