From 71c4b5e33f09f700b2a924adc8a0cc7316ae997d Mon Sep 17 00:00:00 2001 From: giles Date: Tue, 5 May 2026 11:24:50 +0000 Subject: [PATCH] =?UTF-8?q?cl:=20Phase=203=20all=20complete=20=E2=80=94=20?= =?UTF-8?q?conformance.sh=20runner,=20363/363=20tests=20green?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit conformance.sh runs all 7 test suites (reader/parser/eval/conditions/ restart-demo/parse-recover/interactive-debugger), writes scoreboard.json and scoreboard.md. 363 total tests: 79 tokenizer, 31 parser/lambda-lists, 174 evaluator (including unwind-protect), 59 conditions, 20 classic programs. Phase 3 fully complete — all roadmap boxes ticked. Co-Authored-By: Claude Sonnet 4.6 --- lib/common-lisp/conformance.sh | 141 ++++++++++++++++++++++++++++++++ lib/common-lisp/scoreboard.json | 14 ++++ lib/common-lisp/scoreboard.md | 15 ++++ plans/common-lisp-on-sx.md | 3 +- 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100755 lib/common-lisp/conformance.sh create mode 100644 lib/common-lisp/scoreboard.json create mode 100644 lib/common-lisp/scoreboard.md diff --git a/lib/common-lisp/conformance.sh b/lib/common-lisp/conformance.sh new file mode 100755 index 00000000..f8693661 --- /dev/null +++ b/lib/common-lisp/conformance.sh @@ -0,0 +1,141 @@ +#!/usr/bin/env bash +# lib/common-lisp/conformance.sh — CL-on-SX conformance test runner +# +# Runs all Common Lisp test suites and writes scoreboard.json + scoreboard.md. +# +# Usage: +# bash lib/common-lisp/conformance.sh +# bash lib/common-lisp/conformance.sh -v + +set -uo pipefail +cd "$(git rev-parse --show-toplevel)" + +SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}" +if [ ! -x "$SX_SERVER" ]; then + SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe" +fi +if [ ! -x "$SX_SERVER" ]; then + echo "ERROR: sx_server.exe not found." + exit 1 +fi + +VERBOSE="${1:-}" +TOTAL_PASS=0; TOTAL_FAIL=0 +SUITE_NAMES=() +SUITE_PASS=() +SUITE_FAIL=() + +# run_suite NAME "file1 file2 ..." PASS_VAR FAIL_VAR FAILURES_VAR +run_suite() { + local name="$1" load_files="$2" pass_var="$3" fail_var="$4" failures_var="$5" + local TMP; TMP=$(mktemp) + { + printf '(epoch 1)\n(load "spec/stdlib.sx")\n' + local i=2 + for f in $load_files; do + printf '(epoch %d)\n(load "%s")\n' "$i" "$f" + i=$((i+1)) + done + printf '(epoch 100)\n(eval "%s")\n' "$pass_var" + printf '(epoch 101)\n(eval "%s")\n' "$fail_var" + } > "$TMP" + local OUT; OUT=$(timeout 30 "$SX_SERVER" < "$TMP" 2>/dev/null) + rm -f "$TMP" + local P F + P=$(echo "$OUT" | grep -A1 "^(ok-len 100 " | tail -1 | tr -d ' ()' || true) + F=$(echo "$OUT" | grep -A1 "^(ok-len 101 " | tail -1 | tr -d ' ()' || true) + # Also try plain (ok 100 N) format + [ -z "$P" ] && P=$(echo "$OUT" | grep "^(ok 100 " | awk '{print $3}' | tr -d ')' || true) + [ -z "$F" ] && F=$(echo "$OUT" | grep "^(ok 101 " | awk '{print $3}' | tr -d ')' || true) + [ -z "$P" ] && P=0; [ -z "$F" ] && F=0 + SUITE_NAMES+=("$name") + SUITE_PASS+=("$P") + SUITE_FAIL+=("$F") + TOTAL_PASS=$((TOTAL_PASS + P)) + TOTAL_FAIL=$((TOTAL_FAIL + F)) + if [ "$F" = "0" ] && [ "${P:-0}" -gt 0 ] 2>/dev/null; then + echo " PASS $name ($P tests)" + else + echo " FAIL $name ($P passed, $F failed)" + fi +} + +echo "=== Common Lisp on SX — Conformance Run ===" +echo "" + +run_suite "Phase 1: tokenizer/reader" \ + "lib/common-lisp/reader.sx lib/common-lisp/tests/read.sx" \ + "cl-test-pass" "cl-test-fail" "cl-test-fails" + +run_suite "Phase 1: parser/lambda-lists" \ + "lib/common-lisp/reader.sx lib/common-lisp/parser.sx lib/common-lisp/tests/lambda.sx" \ + "cl-test-pass" "cl-test-fail" "cl-test-fails" + +run_suite "Phase 2: evaluator" \ + "lib/common-lisp/reader.sx lib/common-lisp/parser.sx lib/common-lisp/eval.sx lib/common-lisp/tests/eval.sx" \ + "cl-test-pass" "cl-test-fail" "cl-test-fails" + +run_suite "Phase 3: condition system" \ + "lib/common-lisp/runtime.sx lib/common-lisp/tests/conditions.sx" \ + "passed" "failed" "failures" + +run_suite "Phase 3: restart-demo" \ + "lib/common-lisp/runtime.sx lib/common-lisp/tests/programs/restart-demo.sx" \ + "demo-passed" "demo-failed" "demo-failures" + +run_suite "Phase 3: parse-recover" \ + "lib/common-lisp/runtime.sx lib/common-lisp/tests/programs/parse-recover.sx" \ + "parse-passed" "parse-failed" "parse-failures" + +run_suite "Phase 3: interactive-debugger" \ + "lib/common-lisp/runtime.sx lib/common-lisp/tests/programs/interactive-debugger.sx" \ + "debugger-passed" "debugger-failed" "debugger-failures" + +echo "" +echo "=== Total: $TOTAL_PASS passed, $TOTAL_FAIL failed ===" + +# ── write scoreboard.json ───────────────────────────────────────────────── + +SCORE_DIR="lib/common-lisp" +JSON="$SCORE_DIR/scoreboard.json" +{ + printf '{\n' + printf ' "generated": "%s",\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" + printf ' "total_pass": %d,\n' "$TOTAL_PASS" + printf ' "total_fail": %d,\n' "$TOTAL_FAIL" + printf ' "suites": [\n' + first=true + for i in "${!SUITE_NAMES[@]}"; do + if [ "$first" = "true" ]; then first=false; else printf ',\n'; fi + printf ' {"name": "%s", "pass": %d, "fail": %d}' \ + "${SUITE_NAMES[$i]}" "${SUITE_PASS[$i]}" "${SUITE_FAIL[$i]}" + done + printf '\n ]\n' + printf '}\n' +} > "$JSON" + +# ── write scoreboard.md ─────────────────────────────────────────────────── + +MD="$SCORE_DIR/scoreboard.md" +{ + printf '# Common Lisp on SX — Scoreboard\n\n' + printf '_Generated: %s_\n\n' "$(date -u '+%Y-%m-%d %H:%M UTC')" + printf '| Suite | Pass | Fail | Status |\n' + printf '|-------|------|------|--------|\n' + for i in "${!SUITE_NAMES[@]}"; do + p="${SUITE_PASS[$i]}" f="${SUITE_FAIL[$i]}" + status="" + if [ "$f" = "0" ] && [ "${p:-0}" -gt 0 ] 2>/dev/null; then + status="pass" + else + status="FAIL" + fi + printf '| %s | %s | %s | %s |\n' "${SUITE_NAMES[$i]}" "$p" "$f" "$status" + done + printf '\n**Total: %d passed, %d failed**\n' "$TOTAL_PASS" "$TOTAL_FAIL" +} > "$MD" + +echo "" +echo "Scoreboard written to $JSON and $MD" + +[ "$TOTAL_FAIL" -eq 0 ] diff --git a/lib/common-lisp/scoreboard.json b/lib/common-lisp/scoreboard.json new file mode 100644 index 00000000..ef70efb9 --- /dev/null +++ b/lib/common-lisp/scoreboard.json @@ -0,0 +1,14 @@ +{ + "generated": "2026-05-05T11:24:34Z", + "total_pass": 363, + "total_fail": 0, + "suites": [ + {"name": "Phase 1: tokenizer/reader", "pass": 79, "fail": 0}, + {"name": "Phase 1: parser/lambda-lists", "pass": 31, "fail": 0}, + {"name": "Phase 2: evaluator", "pass": 174, "fail": 0}, + {"name": "Phase 3: condition system", "pass": 59, "fail": 0}, + {"name": "Phase 3: restart-demo", "pass": 7, "fail": 0}, + {"name": "Phase 3: parse-recover", "pass": 6, "fail": 0}, + {"name": "Phase 3: interactive-debugger", "pass": 7, "fail": 0} + ] +} diff --git a/lib/common-lisp/scoreboard.md b/lib/common-lisp/scoreboard.md new file mode 100644 index 00000000..37b8e399 --- /dev/null +++ b/lib/common-lisp/scoreboard.md @@ -0,0 +1,15 @@ +# Common Lisp on SX — Scoreboard + +_Generated: 2026-05-05 11:24 UTC_ + +| Suite | Pass | Fail | Status | +|-------|------|------|--------| +| Phase 1: tokenizer/reader | 79 | 0 | pass | +| Phase 1: parser/lambda-lists | 31 | 0 | pass | +| Phase 2: evaluator | 174 | 0 | pass | +| Phase 3: condition system | 59 | 0 | pass | +| Phase 3: restart-demo | 7 | 0 | pass | +| Phase 3: parse-recover | 6 | 0 | pass | +| Phase 3: interactive-debugger | 7 | 0 | pass | + +**Total: 363 passed, 0 failed** diff --git a/plans/common-lisp-on-sx.md b/plans/common-lisp-on-sx.md index 8bcbdf04..acabfd85 100644 --- a/plans/common-lisp-on-sx.md +++ b/plans/common-lisp-on-sx.md @@ -78,7 +78,7 @@ Core mapping: - [x] `restart-demo.sx` — division with `use-zero` and `retry` restarts (7 tests) - [x] `parse-recover.sx` — parser with skipped-token restart (6 tests) - [x] `interactive-debugger.sx` — policy-driven debugger hook, *debugger-hook* global (7 tests) -- [ ] `lib/common-lisp/conformance.sh` + runner, `scoreboard.json` + `scoreboard.md` +- [x] `lib/common-lisp/conformance.sh` + runner, `scoreboard.json` + `scoreboard.md` (363 total tests) ### Phase 4 — CLOS - [ ] `defclass` with `:initarg`/`:initform`/`:accessor`/`:reader`/`:writer`/`:allocation` @@ -124,6 +124,7 @@ data; format for string templating. _Newest first._ +- 2026-05-05: Phase 3 fully complete — conformance.sh runner + scoreboard.json/scoreboard.md; 363 total tests across all suites (79 reader, 31 parser, 174 eval, 59 conditions, 7+6+7 classic programs). - 2026-05-05: Phase 3 complete — cl-debugger-hook/cl-invoke-debugger in runtime.sx (cl-error routes through hook), cl-break-on-signals (fires hook before handlers on type match), cl-invoke-restart-interactively (calls fn with no args); 4 new tests (147 total). Phase 3 all boxes ticked. - 2026-05-05: Phase 3 interactive-debugger.sx — cl-debugger-hook global, cl-invoke-debugger, cl-error-with-debugger, make-policy-debugger; 7 tests (143 total). Tests wired into test.sh program suite runner. Phase 3 condition core complete. - 2026-05-05: Phase 3 classic programs — `tests/programs/restart-demo.sx` (7 tests: safe-divide with use-zero + retry restarts) and `tests/programs/parse-recover.sx` (6 tests: token parser with skip-token + use-zero restarts, handler-case abort). Key gotcha: use `=` not `equal?` for list comparison in sx_server.