- evaluator.py: replace 1200 lines of hand-written eval with thin shim that re-exports from bootstrapped sx_ref.py - bootstrap_py.py: emit all fn-bodied defines as `def` (not `lambda`), flatten tail-position if/cond/case/when to if/elif with returns, fix &rest handling in _emit_define_as_def - platform_py.py: EvalError imports from evaluator.py so catches work - __init__.py: remove SX_USE_REF conditional, always use bootstrapped - tests/run.py: reset render_active after render tests for isolation - Removes setrecursionlimit(5000) hack — no longer needed with flat code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
95 lines
2.7 KiB
Python
95 lines
2.7 KiB
Python
"""
|
|
S-expression evaluator — thin shim over bootstrapped sx_ref.py.
|
|
|
|
All evaluation logic lives in the spec (shared/sx/ref/eval.sx) and is
|
|
bootstrapped to Python (shared/sx/ref/sx_ref.py). This module re-exports
|
|
the public API and internal helpers under their historical names so that
|
|
existing callers don't need updating.
|
|
|
|
Imports are lazy (inside functions/properties) to avoid circular imports
|
|
during bootstrapping: bootstrap_py.py → parser → __init__ → evaluator → sx_ref.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
def _ref():
|
|
"""Lazy import of the bootstrapped evaluator."""
|
|
from .ref import sx_ref
|
|
return sx_ref
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Public API — these are the most used, so we make them importable directly
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class EvalError(Exception):
|
|
"""Error during expression evaluation.
|
|
|
|
Delegates to the bootstrapped EvalError at runtime but is defined here
|
|
so imports don't fail during bootstrapping.
|
|
"""
|
|
pass
|
|
|
|
|
|
def evaluate(expr, env=None):
|
|
return _ref().evaluate(expr, env)
|
|
|
|
|
|
def make_env(**kwargs):
|
|
return _ref().make_env(**kwargs)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Internal helpers — used by html.py, async_eval.py, handlers.py, etc.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def _eval(expr, env):
|
|
return _ref().eval_expr(expr, env)
|
|
|
|
|
|
def _trampoline(val):
|
|
return _ref().trampoline(val)
|
|
|
|
|
|
def _call_lambda(fn, args, caller_env):
|
|
return _ref().call_lambda(fn, args, caller_env)
|
|
|
|
|
|
def _call_component(comp, raw_args, env):
|
|
return _ref().call_component(comp, raw_args, env)
|
|
|
|
|
|
def _expand_macro(macro, raw_args, env):
|
|
return _ref().expand_macro(macro, raw_args, env)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Special-form wrappers: callers pass (expr, env) with expr[0] = head symbol.
|
|
# sx_ref.py special forms take (args, env) where args = expr[1:].
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def _sf_defcomp(expr, env):
|
|
return _ref().sf_defcomp(expr[1:], env)
|
|
|
|
def _sf_defisland(expr, env):
|
|
return _ref().sf_defisland(expr[1:], env)
|
|
|
|
def _sf_defstyle(expr, env):
|
|
return _ref().sf_defstyle(expr[1:], env)
|
|
|
|
def _sf_defmacro(expr, env):
|
|
return _ref().sf_defmacro(expr[1:], env)
|
|
|
|
def _sf_defhandler(expr, env):
|
|
return _ref().sf_defhandler(expr[1:], env)
|
|
|
|
def _sf_defpage(expr, env):
|
|
return _ref().sf_defpage(expr[1:], env)
|
|
|
|
def _sf_defquery(expr, env):
|
|
return _ref().sf_defquery(expr[1:], env)
|
|
|
|
def _sf_defaction(expr, env):
|
|
return _ref().sf_defaction(expr[1:], env)
|