From bb85532cc65af2c48e7df308eb6164aa7b3f9db3 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 7 Jun 2026 10:28:27 +0000 Subject: [PATCH] conformance: migrate erlang onto shared driver (dict, 761/761 parity) Erlang's suites load into one session and each exposes a pass counter plus a *count* (total) counter rather than a fail counter, so MODE=dict fits directly: each suite's runner is a dict literal {:passed P :failed (- count P) :total count}. No driver change needed (dict mode already supports arbitrary runner expressions). conformance.conf + 3-line shim; historical scoreboard schema preserved. Parity verified 761/761 (0 fail), every suite matching baseline. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/erlang/conformance.conf | 68 +++++++++ lib/erlang/conformance.sh | 163 +--------------------- lib/erlang/scoreboard.md | 1 - plans/agent-briefings/conformance-loop.md | 8 +- 4 files changed, 77 insertions(+), 163 deletions(-) create mode 100644 lib/erlang/conformance.conf diff --git a/lib/erlang/conformance.conf b/lib/erlang/conformance.conf new file mode 100644 index 00000000..5ce68539 --- /dev/null +++ b/lib/erlang/conformance.conf @@ -0,0 +1,68 @@ +# Erlang-on-SX conformance config — sourced by lib/guest/conformance.sh. +# +# Erlang's suites load into one session and each exposes a pass counter and a +# *count* (total) counter — not a fail counter. dict mode fits cleanly: each +# runner is a dict literal computing :failed as count - pass. (counters mode +# would misread the count counter as a fail counter.) + +LANG_NAME=erlang +MODE=dict + +PRELOADS=( + lib/erlang/tokenizer.sx + lib/erlang/parser.sx + lib/erlang/parser-core.sx + lib/erlang/parser-expr.sx + lib/erlang/parser-module.sx + lib/erlang/transpile.sx + lib/erlang/runtime.sx + lib/erlang/vm/dispatcher.sx +) + +# name:file:(runner) — runner is a dict literal {:passed :failed :total}. +SUITES=( + "tokenize:lib/erlang/tests/tokenize.sx:{:passed er-test-pass :failed (- er-test-count er-test-pass) :total er-test-count}" + "parse:lib/erlang/tests/parse.sx:{:passed er-parse-test-pass :failed (- er-parse-test-count er-parse-test-pass) :total er-parse-test-count}" + "eval:lib/erlang/tests/eval.sx:{:passed er-eval-test-pass :failed (- er-eval-test-count er-eval-test-pass) :total er-eval-test-count}" + "runtime:lib/erlang/tests/runtime.sx:{:passed er-rt-test-pass :failed (- er-rt-test-count er-rt-test-pass) :total er-rt-test-count}" + "ring:lib/erlang/tests/programs/ring.sx:{:passed er-ring-test-pass :failed (- er-ring-test-count er-ring-test-pass) :total er-ring-test-count}" + "ping-pong:lib/erlang/tests/programs/ping_pong.sx:{:passed er-pp-test-pass :failed (- er-pp-test-count er-pp-test-pass) :total er-pp-test-count}" + "bank:lib/erlang/tests/programs/bank.sx:{:passed er-bank-test-pass :failed (- er-bank-test-count er-bank-test-pass) :total er-bank-test-count}" + "echo:lib/erlang/tests/programs/echo.sx:{:passed er-echo-test-pass :failed (- er-echo-test-count er-echo-test-pass) :total er-echo-test-count}" + "fib:lib/erlang/tests/programs/fib_server.sx:{:passed er-fib-test-pass :failed (- er-fib-test-count er-fib-test-pass) :total er-fib-test-count}" + "ffi:lib/erlang/tests/ffi.sx:{:passed er-ffi-test-pass :failed (- er-ffi-test-count er-ffi-test-pass) :total er-ffi-test-count}" + "vm:lib/erlang/tests/vm.sx:{:passed er-vm-test-pass :failed (- er-vm-test-count er-vm-test-pass) :total er-vm-test-count}" +) + +# Preserve the historical scoreboard schema so consumers of +# lib/erlang/scoreboard.json keep working. +emit_scoreboard_json() { + local n=${#GC_NAMES[@]} i status + printf '{\n' + printf ' "language": "erlang",\n' + printf ' "total_pass": %d,\n' "$GC_TOTAL_PASS" + printf ' "total": %d,\n' "$GC_TOTAL" + printf ' "suites": [' + for ((i=0; i&2 - exit 1 -fi - -VERBOSE="${1:-}" -TMPFILE=$(mktemp) -OUTFILE=$(mktemp) -trap "rm -f $TMPFILE $OUTFILE" EXIT - -# Each suite: name | counter pass | counter total -SUITES=( - "tokenize|er-test-pass|er-test-count" - "parse|er-parse-test-pass|er-parse-test-count" - "eval|er-eval-test-pass|er-eval-test-count" - "runtime|er-rt-test-pass|er-rt-test-count" - "ring|er-ring-test-pass|er-ring-test-count" - "ping-pong|er-pp-test-pass|er-pp-test-count" - "bank|er-bank-test-pass|er-bank-test-count" - "echo|er-echo-test-pass|er-echo-test-count" - "fib|er-fib-test-pass|er-fib-test-count" - "ffi|er-ffi-test-pass|er-ffi-test-count" - "vm|er-vm-test-pass|er-vm-test-count" -) - -cat > "$TMPFILE" << 'EPOCHS' -(epoch 1) -(load "lib/erlang/tokenizer.sx") -(load "lib/erlang/parser.sx") -(load "lib/erlang/parser-core.sx") -(load "lib/erlang/parser-expr.sx") -(load "lib/erlang/parser-module.sx") -(load "lib/erlang/transpile.sx") -(load "lib/erlang/runtime.sx") -(load "lib/erlang/tests/tokenize.sx") -(load "lib/erlang/tests/parse.sx") -(load "lib/erlang/tests/eval.sx") -(load "lib/erlang/tests/runtime.sx") -(load "lib/erlang/tests/programs/ring.sx") -(load "lib/erlang/tests/programs/ping_pong.sx") -(load "lib/erlang/tests/programs/bank.sx") -(load "lib/erlang/tests/programs/echo.sx") -(load "lib/erlang/tests/programs/fib_server.sx") -(load "lib/erlang/vm/dispatcher.sx") -(load "lib/erlang/tests/ffi.sx") -(load "lib/erlang/tests/vm.sx") -(epoch 100) -(eval "(list er-test-pass er-test-count)") -(epoch 101) -(eval "(list er-parse-test-pass er-parse-test-count)") -(epoch 102) -(eval "(list er-eval-test-pass er-eval-test-count)") -(epoch 103) -(eval "(list er-rt-test-pass er-rt-test-count)") -(epoch 104) -(eval "(list er-ring-test-pass er-ring-test-count)") -(epoch 105) -(eval "(list er-pp-test-pass er-pp-test-count)") -(epoch 106) -(eval "(list er-bank-test-pass er-bank-test-count)") -(epoch 107) -(eval "(list er-echo-test-pass er-echo-test-count)") -(epoch 108) -(eval "(list er-fib-test-pass er-fib-test-count)") -(epoch 109) -(eval "(list er-ffi-test-pass er-ffi-test-count)") -(epoch 110) -(eval "(list er-vm-test-pass er-vm-test-count)") -EPOCHS - -timeout 600 "$SX_SERVER" < "$TMPFILE" > "$OUTFILE" 2>&1 - -# Parse "(N M)" from the line after each "(ok-len ...)" marker. -parse_pair() { - local epoch="$1" - local line - line=$(grep -A1 "^(ok-len $epoch " "$OUTFILE" | tail -1) - echo "$line" | sed -E 's/[()]//g' -} - -TOTAL_PASS=0 -TOTAL_COUNT=0 -JSON_SUITES="" -MD_ROWS="" - -idx=0 -for entry in "${SUITES[@]}"; do - name="${entry%%|*}" - epoch=$((100 + idx)) - pair=$(parse_pair "$epoch") - pass=$(echo "$pair" | awk '{print $1}') - count=$(echo "$pair" | awk '{print $2}') - if [ -z "$pass" ] || [ -z "$count" ]; then - pass=0 - count=0 - fi - TOTAL_PASS=$((TOTAL_PASS + pass)) - TOTAL_COUNT=$((TOTAL_COUNT + count)) - status="ok" - marker="✅" - if [ "$pass" != "$count" ]; then - status="fail" - marker="❌" - fi - if [ "$VERBOSE" = "-v" ]; then - printf " %-12s %s/%s\n" "$name" "$pass" "$count" - fi - if [ -n "$JSON_SUITES" ]; then JSON_SUITES+=","; fi - JSON_SUITES+=$'\n ' - JSON_SUITES+="{\"name\":\"$name\",\"pass\":$pass,\"total\":$count,\"status\":\"$status\"}" - MD_ROWS+="| $marker | $name | $pass | $count |"$'\n' - idx=$((idx + 1)) -done - -printf '\nErlang-on-SX conformance: %d / %d\n' "$TOTAL_PASS" "$TOTAL_COUNT" - -# scoreboard.json -cat > lib/erlang/scoreboard.json < lib/erlang/scoreboard.md <