Delete evaluator.py shim: all imports go directly to bootstrapped sx_ref.py
EvalError moved to types.py. All 27 files updated to import eval_expr, trampoline, call_lambda, etc. directly from shared.sx.ref.sx_ref instead of through the evaluator.py indirection layer. 320/320 spec tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,11 +31,8 @@ from .parser import (
|
|||||||
parse_all,
|
parse_all,
|
||||||
serialize,
|
serialize,
|
||||||
)
|
)
|
||||||
from .evaluator import (
|
from .types import EvalError
|
||||||
EvalError,
|
from .ref.sx_ref import evaluate, make_env
|
||||||
evaluate,
|
|
||||||
make_env,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .primitives import (
|
from .primitives import (
|
||||||
all_primitives,
|
all_primitives,
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ from .types import Component, Island, Keyword, Lambda, Macro, NIL, Symbol
|
|||||||
_expand_components: contextvars.ContextVar[bool] = contextvars.ContextVar(
|
_expand_components: contextvars.ContextVar[bool] = contextvars.ContextVar(
|
||||||
"_expand_components", default=False
|
"_expand_components", default=False
|
||||||
)
|
)
|
||||||
from .evaluator import _expand_macro, EvalError
|
from .ref.sx_ref import expand_macro as _expand_macro
|
||||||
|
from .types import EvalError
|
||||||
from .primitives import _PRIMITIVES
|
from .primitives import _PRIMITIVES
|
||||||
from .primitives_io import IO_PRIMITIVES, RequestContext, execute_io
|
from .primitives_io import IO_PRIMITIVES, RequestContext, execute_io
|
||||||
from .parser import SxExpr, serialize
|
from .parser import SxExpr, serialize
|
||||||
@@ -420,23 +421,23 @@ async def _asf_define(expr, env, ctx):
|
|||||||
|
|
||||||
|
|
||||||
async def _asf_defcomp(expr, env, ctx):
|
async def _asf_defcomp(expr, env, ctx):
|
||||||
from .evaluator import _sf_defcomp
|
from .ref.sx_ref import sf_defcomp
|
||||||
return _sf_defcomp(expr, env)
|
return sf_defcomp(expr[1:], env)
|
||||||
|
|
||||||
|
|
||||||
async def _asf_defstyle(expr, env, ctx):
|
async def _asf_defstyle(expr, env, ctx):
|
||||||
from .evaluator import _sf_defstyle
|
from .ref.sx_ref import sf_defstyle
|
||||||
return _sf_defstyle(expr, env)
|
return sf_defstyle(expr[1:], env)
|
||||||
|
|
||||||
|
|
||||||
async def _asf_defmacro(expr, env, ctx):
|
async def _asf_defmacro(expr, env, ctx):
|
||||||
from .evaluator import _sf_defmacro
|
from .ref.sx_ref import sf_defmacro
|
||||||
return _sf_defmacro(expr, env)
|
return sf_defmacro(expr[1:], env)
|
||||||
|
|
||||||
|
|
||||||
async def _asf_defhandler(expr, env, ctx):
|
async def _asf_defhandler(expr, env, ctx):
|
||||||
from .evaluator import _sf_defhandler
|
from .ref.sx_ref import sf_defhandler
|
||||||
return _sf_defhandler(expr, env)
|
return sf_defhandler(expr[1:], env)
|
||||||
|
|
||||||
|
|
||||||
async def _asf_begin(expr, env, ctx):
|
async def _asf_begin(expr, env, ctx):
|
||||||
@@ -599,7 +600,7 @@ async def _asf_reset(expr, env, ctx):
|
|||||||
_ASYNC_RESET_RESUME.append(value if value is not None else NIL)
|
_ASYNC_RESET_RESUME.append(value if value is not None else NIL)
|
||||||
try:
|
try:
|
||||||
# Sync re-evaluation; the async caller will trampoline
|
# Sync re-evaluation; the async caller will trampoline
|
||||||
from .evaluator import _eval as sync_eval, _trampoline
|
from .ref.sx_ref import eval_expr as sync_eval, trampoline as _trampoline
|
||||||
return _trampoline(sync_eval(body, env))
|
return _trampoline(sync_eval(body, env))
|
||||||
finally:
|
finally:
|
||||||
_ASYNC_RESET_RESUME.pop()
|
_ASYNC_RESET_RESUME.pop()
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
"""
|
|
||||||
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)
|
|
||||||
@@ -70,10 +70,7 @@ def load_handler_file(filepath: str, service_name: str) -> list[HandlerDef]:
|
|||||||
"""Parse an .sx file, evaluate it, and register any HandlerDef values."""
|
"""Parse an .sx file, evaluate it, and register any HandlerDef values."""
|
||||||
from .parser import parse_all
|
from .parser import parse_all
|
||||||
import os
|
import os
|
||||||
if os.environ.get("SX_USE_REF") == "1":
|
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
||||||
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
|
||||||
else:
|
|
||||||
from .evaluator import _eval as _raw_eval, _trampoline
|
|
||||||
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
||||||
from .jinja_bridge import get_component_env
|
from .jinja_bridge import get_component_env
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import contextvars
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from .types import Component, Island, Keyword, Lambda, Macro, NIL, Symbol
|
from .types import Component, Island, Keyword, Lambda, Macro, NIL, Symbol
|
||||||
from .evaluator import _eval as _raw_eval, _call_component as _raw_call_component, _expand_macro, _trampoline
|
from .ref.sx_ref import eval_expr as _raw_eval, call_component as _raw_call_component, expand_macro as _expand_macro, trampoline as _trampoline
|
||||||
|
|
||||||
def _eval(expr, env):
|
def _eval(expr, env):
|
||||||
"""Evaluate and unwrap thunks — all html.py _eval calls are non-tail."""
|
"""Evaluate and unwrap thunks — all html.py _eval calls are non-tail."""
|
||||||
|
|||||||
@@ -229,10 +229,7 @@ def register_components(sx_source: str) -> None:
|
|||||||
(div :class "..." (div :class "..." title)))))
|
(div :class "..." (div :class "..." title)))))
|
||||||
''')
|
''')
|
||||||
"""
|
"""
|
||||||
if _os.environ.get("SX_USE_REF") == "1":
|
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
||||||
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
|
||||||
else:
|
|
||||||
from .evaluator import _eval as _raw_eval, _trampoline
|
|
||||||
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
||||||
from .parser import parse_all
|
from .parser import parse_all
|
||||||
from .css_registry import scan_classes_from_sx
|
from .css_registry import scan_classes_from_sx
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ def get_page_helpers(service: str) -> dict[str, Any]:
|
|||||||
def load_page_file(filepath: str, service_name: str) -> list[PageDef]:
|
def load_page_file(filepath: str, service_name: str) -> list[PageDef]:
|
||||||
"""Parse an .sx file, evaluate it, and register any PageDef values."""
|
"""Parse an .sx file, evaluate it, and register any PageDef values."""
|
||||||
from .parser import parse_all
|
from .parser import parse_all
|
||||||
from .evaluator import _eval as _raw_eval, _trampoline
|
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
||||||
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
||||||
from .jinja_bridge import get_component_env
|
from .jinja_bridge import get_component_env
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ def _resolve_sx_reader_macro(name: str):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from .jinja_bridge import get_component_env
|
from .jinja_bridge import get_component_env
|
||||||
from .evaluator import _trampoline, _call_lambda
|
from .ref.sx_ref import trampoline as _trampoline, call_lambda as _call_lambda
|
||||||
from .types import Lambda
|
from .types import Lambda
|
||||||
except ImportError:
|
except ImportError:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ def clear(service: str | None = None) -> None:
|
|||||||
def load_query_file(filepath: str, service_name: str) -> list[QueryDef]:
|
def load_query_file(filepath: str, service_name: str) -> list[QueryDef]:
|
||||||
"""Parse an .sx file and register any defquery definitions."""
|
"""Parse an .sx file and register any defquery definitions."""
|
||||||
from .parser import parse_all
|
from .parser import parse_all
|
||||||
from .evaluator import _eval as _raw_eval, _trampoline
|
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
||||||
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
||||||
from .jinja_bridge import get_component_env
|
from .jinja_bridge import get_component_env
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ def load_query_file(filepath: str, service_name: str) -> list[QueryDef]:
|
|||||||
def load_action_file(filepath: str, service_name: str) -> list[ActionDef]:
|
def load_action_file(filepath: str, service_name: str) -> list[ActionDef]:
|
||||||
"""Parse an .sx file and register any defaction definitions."""
|
"""Parse an .sx file and register any defaction definitions."""
|
||||||
from .parser import parse_all
|
from .parser import parse_all
|
||||||
from .evaluator import _eval as _raw_eval, _trampoline
|
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
||||||
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
_eval = lambda expr, env: _trampoline(_raw_eval(expr, env))
|
||||||
from .jinja_bridge import get_component_env
|
from .jinja_bridge import get_component_env
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ def _emit_py(suites: list[dict], preamble: list) -> str:
|
|||||||
lines.append('')
|
lines.append('')
|
||||||
lines.append('import pytest')
|
lines.append('import pytest')
|
||||||
lines.append('from shared.sx.parser import parse_all')
|
lines.append('from shared.sx.parser import parse_all')
|
||||||
lines.append('from shared.sx.evaluator import _eval, _trampoline')
|
lines.append('from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline')
|
||||||
lines.append('')
|
lines.append('')
|
||||||
lines.append('')
|
lines.append('')
|
||||||
lines.append(f"_PREAMBLE = '''{preamble_escaped}'''")
|
lines.append(f"_PREAMBLE = '''{preamble_escaped}'''")
|
||||||
|
|||||||
@@ -600,7 +600,7 @@ def sx_expr_source(x):
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from shared.sx.evaluator import EvalError
|
from shared.sx.types import EvalError
|
||||||
except ImportError:
|
except ImportError:
|
||||||
class EvalError(Exception):
|
class EvalError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ def _get_z3_env() -> dict[str, Any]:
|
|||||||
return _z3_env
|
return _z3_env
|
||||||
|
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import make_env, _eval, _trampoline
|
from shared.sx.ref.sx_ref import make_env, eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
env = make_env()
|
env = make_env()
|
||||||
z3_path = os.path.join(os.path.dirname(__file__), "z3.sx")
|
z3_path = os.path.join(os.path.dirname(__file__), "z3.sx")
|
||||||
@@ -60,7 +60,7 @@ def z3_translate(expr: Any) -> str:
|
|||||||
|
|
||||||
Delegates to z3-translate defined in z3.sx.
|
Delegates to z3-translate defined in z3.sx.
|
||||||
"""
|
"""
|
||||||
from shared.sx.evaluator import _trampoline, _call_lambda
|
from shared.sx.ref.sx_ref import trampoline as _trampoline, call_lambda as _call_lambda
|
||||||
|
|
||||||
env = _get_z3_env()
|
env = _get_z3_env()
|
||||||
return _trampoline(_call_lambda(env["z3-translate"], [expr], env))
|
return _trampoline(_call_lambda(env["z3-translate"], [expr], env))
|
||||||
@@ -72,7 +72,7 @@ def z3_translate_file(source: str) -> str:
|
|||||||
Delegates to z3-translate-file defined in z3.sx.
|
Delegates to z3-translate-file defined in z3.sx.
|
||||||
"""
|
"""
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import _trampoline, _call_lambda
|
from shared.sx.ref.sx_ref import trampoline as _trampoline, call_lambda as _call_lambda
|
||||||
|
|
||||||
env = _get_z3_env()
|
env = _get_z3_env()
|
||||||
exprs = parse_all(source)
|
exprs = parse_all(source)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def load_js_sx() -> dict:
|
|||||||
|
|
||||||
exprs = parse_all(source)
|
exprs = parse_all(source)
|
||||||
|
|
||||||
from shared.sx.evaluator import evaluate, make_env
|
from shared.sx.ref.sx_ref import evaluate, make_env
|
||||||
|
|
||||||
env = make_env()
|
env = make_env()
|
||||||
for expr in exprs:
|
for expr in exprs:
|
||||||
@@ -74,7 +74,7 @@ def compile_ref_to_js(
|
|||||||
spec_modules: List of spec modules (deps, router, signals). None = auto.
|
spec_modules: List of spec modules (deps, router, signals). None = auto.
|
||||||
"""
|
"""
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from shared.sx.evaluator import evaluate
|
from shared.sx.ref.sx_ref import evaluate
|
||||||
|
|
||||||
ref_dir = _HERE
|
ref_dir = _HERE
|
||||||
env = load_js_sx()
|
env = load_js_sx()
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ def load_py_sx(evaluator_env: dict) -> dict:
|
|||||||
exprs = parse_all(source)
|
exprs = parse_all(source)
|
||||||
|
|
||||||
# Import the evaluator
|
# Import the evaluator
|
||||||
from shared.sx.evaluator import evaluate, make_env
|
from shared.sx.ref.sx_ref import evaluate, make_env
|
||||||
|
|
||||||
env = make_env()
|
env = make_env()
|
||||||
for expr in exprs:
|
for expr in exprs:
|
||||||
@@ -60,7 +60,7 @@ def extract_defines(source: str) -> list[tuple[str, list]]:
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
from shared.sx.evaluator import evaluate
|
from shared.sx.ref.sx_ref import evaluate
|
||||||
|
|
||||||
# Load py.sx into evaluator
|
# Load py.sx into evaluator
|
||||||
env = load_py_sx({})
|
env = load_py_sx({})
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ def sx_expr_source(x):
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from shared.sx.evaluator import EvalError
|
from shared.sx.types import EvalError
|
||||||
except ImportError:
|
except ImportError:
|
||||||
class EvalError(Exception):
|
class EvalError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import asyncio
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from .types import Component, Keyword, Lambda, NIL, Symbol
|
from .types import Component, Keyword, Lambda, NIL, Symbol
|
||||||
from .evaluator import _eval as _raw_eval, _trampoline
|
from .ref.sx_ref import eval_expr as _raw_eval, trampoline as _trampoline
|
||||||
|
|
||||||
def _eval(expr, env):
|
def _eval(expr, env):
|
||||||
"""Evaluate and unwrap thunks — all resolver.py _eval calls are non-tail."""
|
"""Evaluate and unwrap thunks — all resolver.py _eval calls are non-tail."""
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ _PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..", ".."))
|
|||||||
sys.path.insert(0, _PROJECT)
|
sys.path.insert(0, _PROJECT)
|
||||||
|
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import _eval, _trampoline, _call_lambda
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline, call_lambda as _call_lambda
|
||||||
from shared.sx.types import Symbol, Keyword, Lambda, NIL, Component, Island
|
from shared.sx.types import Symbol, Keyword, Lambda, NIL, Component, Island
|
||||||
|
|
||||||
# --- Test state ---
|
# --- Test state ---
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class TestJsSxTranslation:
|
|||||||
|
|
||||||
def _translate(self, sx_source: str) -> str:
|
def _translate(self, sx_source: str) -> str:
|
||||||
"""Translate a single SX expression to JS using js.sx."""
|
"""Translate a single SX expression to JS using js.sx."""
|
||||||
from shared.sx.evaluator import evaluate
|
from shared.sx.ref.sx_ref import evaluate
|
||||||
env = load_js_sx()
|
env = load_js_sx()
|
||||||
expr = parse(sx_source)
|
expr = parse(sx_source)
|
||||||
env["_def_expr"] = expr
|
env["_def_expr"] = expr
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from shared.sx.deps import (
|
|||||||
|
|
||||||
def make_env(*sx_sources: str) -> dict:
|
def make_env(*sx_sources: str) -> dict:
|
||||||
"""Parse and evaluate component definitions into an env dict."""
|
"""Parse and evaluate component definitions into an env dict."""
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
env: dict = {}
|
env: dict = {}
|
||||||
for source in sx_sources:
|
for source in sx_sources:
|
||||||
exprs = parse_all(source)
|
exprs = parse_all(source)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from shared.sx.deps import (
|
|||||||
|
|
||||||
def make_env(*sx_sources: str) -> dict:
|
def make_env(*sx_sources: str) -> dict:
|
||||||
"""Parse and evaluate component definitions into an env dict."""
|
"""Parse and evaluate component definitions into an env dict."""
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
env: dict = {}
|
env: dict = {}
|
||||||
for source in sx_sources:
|
for source in sx_sources:
|
||||||
exprs = parse_all(source)
|
exprs = parse_all(source)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from shared.sx.deps import (
|
|||||||
|
|
||||||
def make_env(*sx_sources: str) -> dict:
|
def make_env(*sx_sources: str) -> dict:
|
||||||
"""Parse and evaluate component definitions into an env dict."""
|
"""Parse and evaluate component definitions into an env dict."""
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
env: dict = {}
|
env: dict = {}
|
||||||
for source in sx_sources:
|
for source in sx_sources:
|
||||||
exprs = parse_all(source)
|
exprs = parse_all(source)
|
||||||
@@ -282,7 +282,7 @@ class TestIoRoutingLogic:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def _eval(self, src, env):
|
def _eval(self, src, env):
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
result = None
|
result = None
|
||||||
for expr in parse_all(src):
|
for expr in parse_all(src):
|
||||||
result = _trampoline(_eval(expr, env))
|
result = _trampoline(_eval(expr, env))
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class TestDataPageDeps:
|
|||||||
def test_deps_computed_for_data_page(self):
|
def test_deps_computed_for_data_page(self):
|
||||||
from shared.sx.deps import components_needed
|
from shared.sx.deps import components_needed
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
# Define a component
|
# Define a component
|
||||||
env = {}
|
env = {}
|
||||||
@@ -172,7 +172,7 @@ class TestDataPageDeps:
|
|||||||
def test_deps_transitive_for_data_page(self):
|
def test_deps_transitive_for_data_page(self):
|
||||||
from shared.sx.deps import components_needed
|
from shared.sx.deps import components_needed
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
env = {}
|
env = {}
|
||||||
source = """
|
source = """
|
||||||
@@ -205,7 +205,7 @@ class TestDataPipelineSimulation:
|
|||||||
|
|
||||||
def test_full_pipeline(self):
|
def test_full_pipeline(self):
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
# 1. Define a component that uses only pure primitives
|
# 1. Define a component that uses only pure primitives
|
||||||
env = {}
|
env = {}
|
||||||
@@ -236,7 +236,7 @@ class TestDataPipelineSimulation:
|
|||||||
|
|
||||||
def test_pipeline_with_list_data(self):
|
def test_pipeline_with_list_data(self):
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
env = {}
|
env = {}
|
||||||
for expr in pa('''
|
for expr in pa('''
|
||||||
@@ -262,7 +262,7 @@ class TestDataPipelineSimulation:
|
|||||||
def test_pipeline_data_isolation(self):
|
def test_pipeline_data_isolation(self):
|
||||||
"""Different data for the same content produces different results."""
|
"""Different data for the same content produces different results."""
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
env = {}
|
env = {}
|
||||||
for expr in pa('(defcomp ~page (&key title count) (str title ": " count))'):
|
for expr in pa('(defcomp ~page (&key title count) (str title ": " count))'):
|
||||||
@@ -298,7 +298,7 @@ class TestDataCache:
|
|||||||
def _make_env(self, current_time_ms=1000):
|
def _make_env(self, current_time_ms=1000):
|
||||||
"""Create an env with cache functions and a controllable now-ms."""
|
"""Create an env with cache functions and a controllable now-ms."""
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
env = {}
|
env = {}
|
||||||
# Mock now-ms as a callable that returns current_time_ms
|
# Mock now-ms as a callable that returns current_time_ms
|
||||||
@@ -344,7 +344,7 @@ class TestDataCache:
|
|||||||
|
|
||||||
def _eval(self, src, env):
|
def _eval(self, src, env):
|
||||||
from shared.sx.parser import parse_all as pa
|
from shared.sx.parser import parse_all as pa
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
result = None
|
result = None
|
||||||
for expr in pa(src):
|
for expr in pa(src):
|
||||||
result = _trampoline(_eval(expr, env))
|
result = _trampoline(_eval(expr, env))
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from shared.sx.types import Symbol, Keyword, Lambda, Component, Macro, NIL
|
|||||||
|
|
||||||
def hw_eval(text, env=None):
|
def hw_eval(text, env=None):
|
||||||
"""Evaluate via hand-written evaluator.py."""
|
"""Evaluate via hand-written evaluator.py."""
|
||||||
from shared.sx.evaluator import evaluate as _evaluate, EvalError
|
from shared.sx.ref.sx_ref import evaluate as _evaluate
|
||||||
if env is None:
|
if env is None:
|
||||||
env = {}
|
env = {}
|
||||||
return _evaluate(parse(text), env)
|
return _evaluate(parse(text), env)
|
||||||
@@ -50,7 +50,7 @@ def ref_render(text, env=None):
|
|||||||
|
|
||||||
def hw_eval_multi(text, env=None):
|
def hw_eval_multi(text, env=None):
|
||||||
"""Evaluate multiple expressions (e.g. defines then call)."""
|
"""Evaluate multiple expressions (e.g. defines then call)."""
|
||||||
from shared.sx.evaluator import evaluate as _evaluate
|
from shared.sx.ref.sx_ref import evaluate as _evaluate
|
||||||
if env is None:
|
if env is None:
|
||||||
env = {}
|
env = {}
|
||||||
result = None
|
result = None
|
||||||
@@ -736,7 +736,7 @@ class TestParityDeps:
|
|||||||
|
|
||||||
class TestParityErrors:
|
class TestParityErrors:
|
||||||
def test_undefined_symbol(self):
|
def test_undefined_symbol(self):
|
||||||
from shared.sx.evaluator import EvalError as HwError
|
from shared.sx.types import EvalError as HwError
|
||||||
from shared.sx.ref.sx_ref import EvalError as RefError
|
from shared.sx.ref.sx_ref import EvalError as RefError
|
||||||
with pytest.raises(HwError):
|
with pytest.raises(HwError):
|
||||||
hw_eval("undefined_var")
|
hw_eval("undefined_var")
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import pytest
|
|||||||
|
|
||||||
from shared.sx.parser import parse, parse_all
|
from shared.sx.parser import parse, parse_all
|
||||||
from shared.sx.html import render as py_render
|
from shared.sx.html import render as py_render
|
||||||
from shared.sx.evaluator import evaluate
|
from shared.sx.ref.sx_ref import evaluate
|
||||||
|
|
||||||
SX_JS = Path(__file__).resolve().parents[2] / "static" / "scripts" / "sx.js"
|
SX_JS = Path(__file__).resolve().parents[2] / "static" / "scripts" / "sx.js"
|
||||||
SX_TEST_JS = Path(__file__).resolve().parents[2] / "static" / "scripts" / "sx-test.js"
|
SX_TEST_JS = Path(__file__).resolve().parents[2] / "static" / "scripts" / "sx-test.js"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
|
|
||||||
_PREAMBLE = '''(define assert-equal (fn (expected actual) (assert (equal? expected actual) (str "Expected " (str expected) " but got " (str actual)))))
|
_PREAMBLE = '''(define assert-equal (fn (expected actual) (assert (equal? expected actual) (str "Expected " (str expected) " but got " (str actual)))))
|
||||||
|
|||||||
@@ -375,6 +375,15 @@ class _ShiftSignal(BaseException):
|
|||||||
self.env = env
|
self.env = env
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# EvalError
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class EvalError(Exception):
|
||||||
|
"""Error during expression evaluation."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Type alias
|
# Type alias
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ def _self_hosting_data(ref_dir: str) -> dict:
|
|||||||
import os
|
import os
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.types import Symbol
|
from shared.sx.types import Symbol
|
||||||
from shared.sx.evaluator import evaluate, make_env
|
from shared.sx.ref.sx_ref import evaluate, make_env
|
||||||
from shared.sx.ref.bootstrap_py import extract_defines, compile_ref_to_py, PyEmitter
|
from shared.sx.ref.bootstrap_py import extract_defines, compile_ref_to_py, PyEmitter
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -387,7 +387,7 @@ def _js_self_hosting_data(ref_dir: str) -> dict:
|
|||||||
"""Run js.sx live: load into evaluator, translate all spec defines."""
|
"""Run js.sx live: load into evaluator, translate all spec defines."""
|
||||||
import os
|
import os
|
||||||
from shared.sx.types import Symbol
|
from shared.sx.types import Symbol
|
||||||
from shared.sx.evaluator import evaluate
|
from shared.sx.ref.sx_ref import evaluate
|
||||||
from shared.sx.ref.run_js_sx import load_js_sx
|
from shared.sx.ref.run_js_sx import load_js_sx
|
||||||
from shared.sx.ref.platform_js import extract_defines
|
from shared.sx.ref.platform_js import extract_defines
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ def _run_spec_tests() -> dict:
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
|
|
||||||
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
|
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
|
||||||
if not os.path.isdir(ref_dir):
|
if not os.path.isdir(ref_dir):
|
||||||
@@ -735,7 +735,7 @@ def _run_modular_tests(spec_name: str) -> dict:
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import _eval, _trampoline
|
from shared.sx.ref.sx_ref import eval_expr as _eval, trampoline as _trampoline
|
||||||
from shared.sx.types import Symbol, Keyword, Lambda, NIL
|
from shared.sx.types import Symbol, Keyword, Lambda, NIL
|
||||||
|
|
||||||
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
|
ref_dir = os.path.join(os.path.dirname(__file__), "..", "..", "shared", "sx", "ref")
|
||||||
@@ -817,7 +817,7 @@ def _run_modular_tests(spec_name: str) -> dict:
|
|||||||
|
|
||||||
def _call_sx(fn, args, caller_env):
|
def _call_sx(fn, args, caller_env):
|
||||||
if isinstance(fn, Lambda):
|
if isinstance(fn, Lambda):
|
||||||
from shared.sx.evaluator import _call_lambda
|
from shared.sx.ref.sx_ref import call_lambda as _call_lambda
|
||||||
return _trampoline(_call_lambda(fn, list(args), caller_env))
|
return _trampoline(_call_lambda(fn, list(args), caller_env))
|
||||||
return fn(*args)
|
return fn(*args)
|
||||||
|
|
||||||
@@ -1165,9 +1165,9 @@ def _prove_data() -> dict:
|
|||||||
"""
|
"""
|
||||||
import time
|
import time
|
||||||
from shared.sx.parser import parse_all
|
from shared.sx.parser import parse_all
|
||||||
from shared.sx.evaluator import evaluate
|
from shared.sx.ref.sx_ref import evaluate
|
||||||
from shared.sx.primitives import all_primitives
|
from shared.sx.primitives import all_primitives
|
||||||
from shared.sx.evaluator import _trampoline, _call_lambda
|
from shared.sx.ref.sx_ref import trampoline as _trampoline, call_lambda as _call_lambda
|
||||||
|
|
||||||
env = all_primitives()
|
env = all_primitives()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user