#!/usr/bin/env python3 """Run test.sx directly against the Python SX evaluator. The Python evaluator parses and evaluates test.sx — SX tests itself. This script provides only platform functions (error catching, reporting). Usage: python shared/sx/tests/run.py """ from __future__ import annotations import os import sys import traceback _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.evaluator import _eval, _trampoline # --- Test state --- suite_stack: list[str] = [] passed = 0 failed = 0 test_num = 0 def try_call(thunk): """Call an SX thunk, catching errors.""" try: _trampoline(_eval([thunk], {})) return {"ok": True} except Exception as e: return {"ok": False, "error": str(e)} def report_pass(name): global passed, test_num test_num += 1 passed += 1 full_name = " > ".join(suite_stack + [name]) print(f"ok {test_num} - {full_name}") def report_fail(name, error): global failed, test_num test_num += 1 failed += 1 full_name = " > ".join(suite_stack + [name]) print(f"not ok {test_num} - {full_name}") print(f" # {error}") def push_suite(name): suite_stack.append(name) def pop_suite(): suite_stack.pop() def main(): env = { "try-call": try_call, "report-pass": report_pass, "report-fail": report_fail, "push-suite": push_suite, "pop-suite": pop_suite, } test_sx = os.path.join(_HERE, "..", "ref", "test.sx") with open(test_sx) as f: src = f.read() exprs = parse_all(src) print("TAP version 13") for expr in exprs: _trampoline(_eval(expr, env)) print() print(f"1..{test_num}") print(f"# tests {passed + failed}") print(f"# pass {passed}") if failed > 0: print(f"# fail {failed}") sys.exit(1) if __name__ == "__main__": main()