From bd2f1f4fb07c5c6bf1198dc8a68cd534e74e849c Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Wed, 8 Jul 2026 05:46:39 -0700 Subject: [PATCH 1/7] add tests for go and c++ (c++ expected output pending CI capture) Co-Authored-By: Claude Fable 5 --- languages/c/c++/expected-output.txt | 0 languages/c/c++/test.sh | 6 ++++++ languages/g/go/expected-output.txt | 30 +++++++++++++++++++++++++++++ languages/g/go/test.sh | 1 + 4 files changed, 37 insertions(+) create mode 100644 languages/c/c++/expected-output.txt create mode 100644 languages/c/c++/test.sh create mode 100644 languages/g/go/expected-output.txt create mode 100644 languages/g/go/test.sh diff --git a/languages/c/c++/expected-output.txt b/languages/c/c++/expected-output.txt new file mode 100644 index 0000000..e69de29 diff --git a/languages/c/c++/test.sh b/languages/c/c++/test.sh new file mode 100644 index 0000000..7c72a3d --- /dev/null +++ b/languages/c/c++/test.sh @@ -0,0 +1,6 @@ +CXX=$(command -v g++-14 || command -v g++) +"$CXX" lambda-core.cpp -std=c++23 -o lambda-core.test || exit 1 +./lambda-core.test +status=$? +rm -f lambda-core.test +exit $status diff --git a/languages/g/go/expected-output.txt b/languages/g/go/expected-output.txt new file mode 100644 index 0000000..4ba30d7 --- /dev/null +++ b/languages/g/go/expected-output.txt @@ -0,0 +1,30 @@ +LOGIC +------------- +TRUE/FALSE +true +false +NOT +false +true +AND +true +false +false +false +OR +true +true +true +false + +CHURCH NUMERALS +------------- +ZERO/SUCC +0 +1 +2 +3 +PRED +0 +1 +2 diff --git a/languages/g/go/test.sh b/languages/g/go/test.sh new file mode 100644 index 0000000..4beb55a --- /dev/null +++ b/languages/g/go/test.sh @@ -0,0 +1 @@ +go run . From 3701d786010d00792fc525fc8be891e1dc1f8d26 Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Wed, 8 Jul 2026 05:48:16 -0700 Subject: [PATCH 2/7] capture c++ expected output from CI run Co-Authored-By: Claude Fable 5 --- ROADMAP.md | 2 +- languages/c/c++/expected-output.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index bfd0cc4..c5a59eb 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -15,7 +15,7 @@ Folders without a `test.sh` are skipped until backfilled. - [x] **Step 1 — harness + locally verifiable languages.** Workflow file, `run-tests.sh`, and test.sh/expected-output.txt for Python, JavaScript, TypeScript (Bun), Perl, Racket, and C. All six verified locally. -- [ ] **Step 2 — C++ and Go.** C++ needs GCC 14 (`` header) — not on +- [x] **Step 2 — C++ and Go.** C++ needs GCC 14 (`` header) — not on the dev machine, so capture its output from the CI runner log on the PR, then commit it as the expected file. Go is preinstalled on runners. - [ ] **Step 3 — Ruby, Lua, Haskell.** All installable on the runner via apt diff --git a/languages/c/c++/expected-output.txt b/languages/c/c++/expected-output.txt index e69de29..2cf8dc8 100644 --- a/languages/c/c++/expected-output.txt +++ b/languages/c/c++/expected-output.txt @@ -0,0 +1,2 @@ +true +1 From 5d64c1a3758d28ee73154e0146a41d4953b31451 Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Thu, 9 Jul 2026 07:47:57 -0700 Subject: [PATCH 3/7] add tests for Ruby, Lua, Haskell test.sh + real-run-captured expected-output.txt for each, plus their apt toolchains (ruby, lua5.4, ghc) in the CI workflow. All three PASS locally. Completes roadmap Step 3. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/test.yml | 2 +- ROADMAP.md | 7 ++++-- languages/h/haskell/expected-output.txt | 16 +++++++++++++ languages/h/haskell/test.sh | 1 + languages/l/lua/expected-output.txt | 22 ++++++++++++++++++ languages/l/lua/test.sh | 1 + languages/r/ruby/expected-output.txt | 30 +++++++++++++++++++++++++ languages/r/ruby/test.sh | 1 + 8 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 languages/h/haskell/expected-output.txt create mode 100644 languages/h/haskell/test.sh create mode 100644 languages/l/lua/expected-output.txt create mode 100644 languages/l/lua/test.sh create mode 100644 languages/r/ruby/expected-output.txt create mode 100644 languages/r/ruby/test.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8e5b8ff..b1fc94a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: - name: Install toolchains not preinstalled on the runner run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends racket + sudo apt-get install -y --no-install-recommends racket ruby lua5.4 ghc - uses: oven-sh/setup-bun@v2 diff --git a/ROADMAP.md b/ROADMAP.md index c5a59eb..b9ea769 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -18,8 +18,11 @@ Folders without a `test.sh` are skipped until backfilled. - [x] **Step 2 — C++ and Go.** C++ needs GCC 14 (`` header) — not on the dev machine, so capture its output from the CI runner log on the PR, then commit it as the expected file. Go is preinstalled on runners. -- [ ] **Step 3 — Ruby, Lua, Haskell.** All installable on the runner via apt - (`ruby`, `lua5.4`, `ghc`); add installs to the workflow's toolchain step. +- [x] **Step 3 — Ruby, Lua, Haskell.** `test.sh` added for all three + (`ruby lambda-core.rb`, `lua5.4 lambda-core.lua`, `runghc lambda-core.hs`), + the apt installs (`ruby lua5.4 ghc`) added to the workflow, and each + folder's `expected-output.txt` captured from a real local run. All three + PASS locally. - [ ] **Step 4 — OCaml, Elixir, Clojure, F#.** apt/preinstalled on runners (`ocaml`, `elixir`, `clojure`; F# via preinstalled dotnet). Clojure runs through its own deps.edn test runner — wrap it in test.sh. diff --git a/languages/h/haskell/expected-output.txt b/languages/h/haskell/expected-output.txt new file mode 100644 index 0000000..49e9e5e --- /dev/null +++ b/languages/h/haskell/expected-output.txt @@ -0,0 +1,16 @@ +True +False +False +True +False +False +False +True +False +True +True +True +0 +1 +1 +0 diff --git a/languages/h/haskell/test.sh b/languages/h/haskell/test.sh new file mode 100644 index 0000000..571ee04 --- /dev/null +++ b/languages/h/haskell/test.sh @@ -0,0 +1 @@ +runghc lambda-core.hs diff --git a/languages/l/lua/expected-output.txt b/languages/l/lua/expected-output.txt new file mode 100644 index 0000000..80087d5 --- /dev/null +++ b/languages/l/lua/expected-output.txt @@ -0,0 +1,22 @@ +true +false +false +true +true +false +false +false +true +true +true +false +0 +1 +2 +3 +0 +0 +1 +1 +2 +2 diff --git a/languages/l/lua/test.sh b/languages/l/lua/test.sh new file mode 100644 index 0000000..520a342 --- /dev/null +++ b/languages/l/lua/test.sh @@ -0,0 +1 @@ +lua5.4 lambda-core.lua diff --git a/languages/r/ruby/expected-output.txt b/languages/r/ruby/expected-output.txt new file mode 100644 index 0000000..1b055f1 --- /dev/null +++ b/languages/r/ruby/expected-output.txt @@ -0,0 +1,30 @@ +LOGIC +--------------- +TRUE/FALSE +t +f +NOT +f +t +AND +t +f +f +f +OR +t +t +t +f + +CHURCH NUMERALS +--------------- +ZERO/SUCC +0 +1 +2 +3 +PRED +0 +1 +2 diff --git a/languages/r/ruby/test.sh b/languages/r/ruby/test.sh new file mode 100644 index 0000000..2d8723c --- /dev/null +++ b/languages/r/ruby/test.sh @@ -0,0 +1 @@ +ruby lambda-core.rb From b0baf562390120bcaded7457b42ff9815a59f6f7 Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Thu, 9 Jul 2026 07:58:00 -0700 Subject: [PATCH 4/7] distinguish SKIP/PENDING from FAIL in the test harness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FAIL now means only that a test ran and produced the wrong output or a nonzero exit — a real problem, and the sole reason the script exits nonzero. A toolchain that isn't installed here reads as SKIP (command not found, or exit 42), and a folder with no captured baseline yet reads as PENDING with its output printed for capture. On CI (CI env var set) a SKIP is upgraded to FAIL so a broken toolchain install can't hide. C++ test.sh now requires g++-14 and exits 42 when absent, so an older dev-machine g++ that can't compile C++23 reads as SKIP, not a compile FAIL. Co-Authored-By: Claude Opus 4.8 --- languages/c/c++/test.sh | 9 +++++- run-tests.sh | 64 ++++++++++++++++++++++++++++++++++------- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/languages/c/c++/test.sh b/languages/c/c++/test.sh index 7c72a3d..ea9b07d 100644 --- a/languages/c/c++/test.sh +++ b/languages/c/c++/test.sh @@ -1,4 +1,11 @@ -CXX=$(command -v g++-14 || command -v g++) +# C++23 needs GCC 14+; g++-14 is preinstalled on the CI runner. If it +# isn't present (e.g. an older dev machine) skip (exit 42) rather than fail on a +# plain g++ that can't compile the source. +CXX=$(command -v g++-14) +if [ -z "$CXX" ]; then + echo "g++-14 not found — needs GCC 14+ for C++23 " >&2 + exit 42 +fi "$CXX" lambda-core.cpp -std=c++23 -o lambda-core.test || exit 1 ./lambda-core.test status=$? diff --git a/run-tests.sh b/run-tests.sh index 705f109..0435023 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,35 +1,79 @@ #!/bin/sh -# Runs every language folder that has a test.sh and compares its stdout -# against that folder's expected-output.txt. Exits nonzero if any differ. -# Folders without a test.sh are skipped (not yet backfilled). +# Runs every language folder that has a test.sh and compares its stdout against +# that folder's expected-output.txt. Result categories: +# +# PASS ran, exit 0, output matched the baseline. +# FAIL ran but exited nonzero or output did not match. A real problem. +# This is the ONLY category that makes the script exit nonzero. +# SKIP the language's toolchain is not available in this environment: the +# command was not found (exit 127) or the test.sh opted out (exit 42). +# Skipping is normal locally for CI-only toolchains. On CI (the CI env +# var is set) a skip is upgraded to a FAIL, because the runner is +# supposed to have every toolchain installed — a missing one there is +# a broken install, not an expected absence. +# PENDING the folder has a test.sh but no expected-output.txt baseline yet. +# Its output is printed so it can be captured; never a failure. +# +# Folders without a test.sh are skipped entirely (not yet backfilled). set -u root=$(cd "$(dirname "$0")" && pwd) +on_ci=${CI:-} + +pass=0 fail=0 -ran=0 +skip=0 +pending=0 +failed_names="" for script in "$root"/languages/*/*/test.sh; do [ -e "$script" ] || continue dir=$(dirname "$script") name=${dir#"$root"/languages/} - ran=$((ran + 1)) + + if [ ! -f "$dir/expected-output.txt" ]; then + actual=$( (cd "$dir" && sh test.sh 2>/dev/null) ) + echo "PENDING $name (no expected-output.txt baseline yet)" + echo "--- captured output (paste into expected-output.txt once verified) ---" + echo "$actual" + echo "---" + pending=$((pending + 1)) + continue + fi actual=$( (cd "$dir" && sh test.sh 2>/dev/null) ) status=$? expected=$(cat "$dir/expected-output.txt") if [ "$status" -eq 0 ] && [ "$actual" = "$expected" ]; then - echo "PASS $name" + echo "PASS $name" + pass=$((pass + 1)) + elif [ "$status" -eq 42 ] || [ "$status" -eq 127 ]; then + if [ -n "$on_ci" ]; then + echo "FAIL $name (toolchain missing on CI — exit $status)" + fail=$((fail + 1)) + failed_names="$failed_names $name" + else + echo "SKIP $name (toolchain not installed here)" + skip=$((skip + 1)) + fi else - echo "FAIL $name (exit $status)" + echo "FAIL $name (exit $status)" echo "--- expected ---" echo "$expected" echo "--- actual ---" echo "$actual" echo "---" - fail=1 + fail=$((fail + 1)) + failed_names="$failed_names $name" fi done -echo "$ran folder(s) tested" -exit $fail +echo +echo "Summary: $pass passed, $fail failed, $skip skipped, $pending pending" +if [ -n "$failed_names" ]; then + echo "FAILED:$failed_names" +fi + +[ "$fail" -eq 0 ] || exit 1 +exit 0 From 1b204af589a403eff64cd0c7909255c6c98b5bd0 Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Thu, 9 Jul 2026 07:58:11 -0700 Subject: [PATCH 5/7] add tests for OCaml, Elixir, F#, Clojure (Step 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test.sh for all four: ocaml lambda_core.ml, elixir lambda-core.exs, dotnet fsi lambda-core.fsx, and cd lambda-core && clj -M:test for the Clojure deps.edn test runner. Workflow installs ocaml+elixir via apt and the Clojure CLI via its official installer; F# uses the runner's preinstalled dotnet. OCaml and Elixir expected-output.txt captured from real local runs and PASSing. F# and Clojure baselines still pending — capture from the CI log per the C++ pattern. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/test.yml | 13 +++++++++-- ROADMAP.md | 11 +++++++--- languages/c/clojure/test.sh | 2 ++ languages/e/elixir/expected-output.txt | 30 ++++++++++++++++++++++++++ languages/e/elixir/test.sh | 1 + languages/f/fsharp/test.sh | 3 +++ languages/o/ocaml/expected-output.txt | 30 ++++++++++++++++++++++++++ languages/o/ocaml/test.sh | 1 + 8 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 languages/c/clojure/test.sh create mode 100644 languages/e/elixir/expected-output.txt create mode 100644 languages/e/elixir/test.sh create mode 100644 languages/f/fsharp/test.sh create mode 100644 languages/o/ocaml/expected-output.txt create mode 100644 languages/o/ocaml/test.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b1fc94a..f727812 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,11 +11,20 @@ jobs: steps: - uses: actions/checkout@v4 - # Python, Node.js, Perl, GCC/G++ 14 come preinstalled on the runner. + # Python, Node.js, Perl, GCC/G++ 14, and the .NET SDK (F#) come + # preinstalled on the runner. - name: Install toolchains not preinstalled on the runner run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends racket ruby lua5.4 ghc + sudo apt-get install -y --no-install-recommends \ + racket ruby lua5.4 ghc ocaml elixir + + # Clojure's deps.edn CLI (clj) is not in apt; use the official installer. + - name: Install Clojure CLI + run: | + curl -L -O https://github.com/clojure/brew-install/releases/latest/download/linux-install.sh + chmod +x linux-install.sh + sudo ./linux-install.sh - uses: oven-sh/setup-bun@v2 diff --git a/ROADMAP.md b/ROADMAP.md index b9ea769..7616adf 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -23,9 +23,14 @@ Folders without a `test.sh` are skipped until backfilled. the apt installs (`ruby lua5.4 ghc`) added to the workflow, and each folder's `expected-output.txt` captured from a real local run. All three PASS locally. -- [ ] **Step 4 — OCaml, Elixir, Clojure, F#.** apt/preinstalled on runners - (`ocaml`, `elixir`, `clojure`; F# via preinstalled dotnet). Clojure runs - through its own deps.edn test runner — wrap it in test.sh. +- [~] **Step 4 — OCaml, Elixir, Clojure, F#.** `test.sh` added for all four + (`ocaml lambda_core.ml`, `elixir lambda-core.exs`, `dotnet fsi + lambda-core.fsx`, and `cd lambda-core && clj -M:test` for Clojure's + deps.edn test runner). Workflow installs `ocaml`+`elixir` via apt and the + Clojure CLI via its official installer; F# uses the runner's preinstalled + dotnet. OCaml + Elixir captured and PASSing locally. Remaining: capture + F# (dotnet) and Clojure (clj CLI) `expected-output.txt` from the CI log — + both are fiddly local installs, so use the C++ pattern instead. - [ ] **Step 5 — Java and Kotlin.** Java: PR #29 (the `java` branch) fixes the numeral typing so PRED works; add test.sh + expected output to that branch, let CI validate it, then merge #29. Kotlin: runner has a JDK; diff --git a/languages/c/clojure/test.sh b/languages/c/clojure/test.sh new file mode 100644 index 0000000..5b04b63 --- /dev/null +++ b/languages/c/clojure/test.sh @@ -0,0 +1,2 @@ +# The Clojure impl is a deps.edn project with its own clojure.test runner. +cd lambda-core && clj -M:test diff --git a/languages/e/elixir/expected-output.txt b/languages/e/elixir/expected-output.txt new file mode 100644 index 0000000..e39dc20 --- /dev/null +++ b/languages/e/elixir/expected-output.txt @@ -0,0 +1,30 @@ +LOGIC +-------------- +TRUE/FALSE +t +f +NOT +f +t +AND +t +f +f +f +OR +t +t +t +f + +CHURCH NUMERALS +-------------- +ZERO/SUCC +0 +1 +2 +3 +PRED +0 +1 +2 diff --git a/languages/e/elixir/test.sh b/languages/e/elixir/test.sh new file mode 100644 index 0000000..2d0d27f --- /dev/null +++ b/languages/e/elixir/test.sh @@ -0,0 +1 @@ +elixir lambda-core.exs diff --git a/languages/f/fsharp/test.sh b/languages/f/fsharp/test.sh new file mode 100644 index 0000000..c14d39c --- /dev/null +++ b/languages/f/fsharp/test.sh @@ -0,0 +1,3 @@ +# DOTNET_NOLOGO / telemetry opt-out keep the first-run banner off stdout so the +# captured output is just the program's. +DOTNET_NOLOGO=1 DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet fsi lambda-core.fsx diff --git a/languages/o/ocaml/expected-output.txt b/languages/o/ocaml/expected-output.txt new file mode 100644 index 0000000..e00ba50 --- /dev/null +++ b/languages/o/ocaml/expected-output.txt @@ -0,0 +1,30 @@ +LOGIC +---------------- +TRUE/FALSE +true +false +NOT +false +true +AND +true +false +false +false +OR +true +true +true +false + +CHURCH NUMERALS +---------------- +ZERO/SUCC +0 +1 +2 +3 +PRED +0 +1 +2 diff --git a/languages/o/ocaml/test.sh b/languages/o/ocaml/test.sh new file mode 100644 index 0000000..3ad92ab --- /dev/null +++ b/languages/o/ocaml/test.sh @@ -0,0 +1 @@ +ocaml lambda_core.ml From 09dee1ee69988c4ee6de2634850b45811b240678 Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Thu, 9 Jul 2026 08:25:45 -0700 Subject: [PATCH 6/7] capture F# expected output from CI; fix Clojure test runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit F# expected-output.txt captured from the PR #31 CI run (its source prints no blank line between the LOGIC and CHURCH NUMERALS sections, unlike the others). F# now PASSes on CI. The first CI run showed Clojure's `clj -M:test` printing "Please install rlwrap ... or use clojure instead" instead of the test output — `clj` is the interactive rlwrap wrapper. Switched to `clojure -M:test`, the non-interactive launcher, to be captured on the next CI run. Co-Authored-By: Claude Opus 4.8 --- ROADMAP.md | 7 ++++--- languages/c/clojure/test.sh | 4 +++- languages/f/fsharp/expected-output.txt | 29 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 languages/f/fsharp/expected-output.txt diff --git a/ROADMAP.md b/ROADMAP.md index 7616adf..8f5289e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -28,9 +28,10 @@ Folders without a `test.sh` are skipped until backfilled. lambda-core.fsx`, and `cd lambda-core && clj -M:test` for Clojure's deps.edn test runner). Workflow installs `ocaml`+`elixir` via apt and the Clojure CLI via its official installer; F# uses the runner's preinstalled - dotnet. OCaml + Elixir captured and PASSing locally. Remaining: capture - F# (dotnet) and Clojure (clj CLI) `expected-output.txt` from the CI log — - both are fiddly local installs, so use the C++ pattern instead. + dotnet. OCaml + Elixir captured locally; F# captured from the CI log (PR + #31). Remaining: Clojure — the first CI run showed `clj` (the interactive + rlwrap wrapper) printing a notice instead of running; switched test.sh to + `clojure -M:test`, capture from the next CI run. - [ ] **Step 5 — Java and Kotlin.** Java: PR #29 (the `java` branch) fixes the numeral typing so PRED works; add test.sh + expected output to that branch, let CI validate it, then merge #29. Kotlin: runner has a JDK; diff --git a/languages/c/clojure/test.sh b/languages/c/clojure/test.sh index 5b04b63..20207d5 100644 --- a/languages/c/clojure/test.sh +++ b/languages/c/clojure/test.sh @@ -1,2 +1,4 @@ # The Clojure impl is a deps.edn project with its own clojure.test runner. -cd lambda-core && clj -M:test +# Use `clojure`, not `clj`: `clj` is the interactive rlwrap wrapper and prints +# an "install rlwrap / use clojure instead" notice when run non-interactively. +cd lambda-core && clojure -M:test diff --git a/languages/f/fsharp/expected-output.txt b/languages/f/fsharp/expected-output.txt new file mode 100644 index 0000000..3d915b6 --- /dev/null +++ b/languages/f/fsharp/expected-output.txt @@ -0,0 +1,29 @@ +LOGIC +---------------- +TRUE/FALSE +true +false +NOT +false +true +AND +true +false +false +false +OR +true +true +true +false +CHURCH NUMERALS +---------------- +ZERO/SUCC +0 +1 +2 +3 +PRED +0 +1 +2 From 0580dae7ca703348c3f8503288634f93ce22d59e Mon Sep 17 00:00:00 2001 From: Kyle Serrecchia Date: Thu, 9 Jul 2026 08:29:10 -0700 Subject: [PATCH 7/7] capture Clojure expected output from CI (completes Step 4) clojure -M:test now runs the deps.edn test runner cleanly; its output (7 tests, 56 assertions, 0 failures) captured from the PR #31 CI log. All four Step-4 languages are green on CI. Co-Authored-By: Claude Opus 4.8 --- ROADMAP.md | 11 ++--- languages/c/clojure/expected-output.txt | 65 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 languages/c/clojure/expected-output.txt diff --git a/ROADMAP.md b/ROADMAP.md index 8f5289e..d5715ea 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -23,15 +23,14 @@ Folders without a `test.sh` are skipped until backfilled. the apt installs (`ruby lua5.4 ghc`) added to the workflow, and each folder's `expected-output.txt` captured from a real local run. All three PASS locally. -- [~] **Step 4 — OCaml, Elixir, Clojure, F#.** `test.sh` added for all four +- [x] **Step 4 — OCaml, Elixir, Clojure, F#.** `test.sh` for all four (`ocaml lambda_core.ml`, `elixir lambda-core.exs`, `dotnet fsi - lambda-core.fsx`, and `cd lambda-core && clj -M:test` for Clojure's + lambda-core.fsx`, and `cd lambda-core && clojure -M:test` for Clojure's deps.edn test runner). Workflow installs `ocaml`+`elixir` via apt and the Clojure CLI via its official installer; F# uses the runner's preinstalled - dotnet. OCaml + Elixir captured locally; F# captured from the CI log (PR - #31). Remaining: Clojure — the first CI run showed `clj` (the interactive - rlwrap wrapper) printing a notice instead of running; switched test.sh to - `clojure -M:test`, capture from the next CI run. + dotnet. OCaml + Elixir captured locally; F# and Clojure captured from the + CI log (PR #31). Clojure uses `clojure`, not the interactive `clj` wrapper + (which printed an rlwrap notice instead of running). All four green on CI. - [ ] **Step 5 — Java and Kotlin.** Java: PR #29 (the `java` branch) fixes the numeral typing so PRED works; add test.sh + expected output to that branch, let CI validate it, then merge #29. Kotlin: runner has a JDK; diff --git a/languages/c/clojure/expected-output.txt b/languages/c/clojure/expected-output.txt new file mode 100644 index 0000000..df8e066 --- /dev/null +++ b/languages/c/clojure/expected-output.txt @@ -0,0 +1,65 @@ + +Testing numerals-test +("numeral expressions") = (toInt ((minus ((mult (fromInt 3)) ((plus (fromInt 2)) (fromInt 5)))) ((exp (fromInt 2)) (fromInt 3)))) => 13 +("addition") = (toInt ((plus (fromInt 7)) (fromInt 5))) => 12 +("addition") = (toInt ((plus (fromInt 7)) ((plus (fromInt 6)) (fromInt 2)))) => 15 +("subtraction") = (toInt ((minus (fromInt 7)) (fromInt 5))) => 2 +("subtraction") = (toInt ((minus (fromInt 7)) ((minus (fromInt 6)) (fromInt 2)))) => 3 +("multiplication") = (toInt ((mult (fromInt 2)) (fromInt 3))) => 6 +("multiplication") = (toInt ((mult (fromInt 2)) ((mult (fromInt 5)) (fromInt 3)))) => 30 +("exponentiation") = (toInt ((exp (fromInt 2)) (fromInt 3))) => 8 +("exponentiation") = (toInt ((exp (fromInt 2)) ((exp (fromInt 2)) (fromInt 3)))) => 256 +("zero") = (toInt zero) => 0 +("one") = (toInt (succ zero)) => 1 +("one") = (toInt one) => 1 +("two") = (toInt (succ (succ zero))) => 2 +("two") = (toInt two) => 2 +("three") = (toInt (succ (succ (succ zero)))) => 3 +("predecessor") = (toInt (pred one)) => 0 +("predecessor") = (toInt (pred two)) => 1 +("predecessor") = (toInt (pred (succ (succ (succ zero))))) => 2 +("predecessor") = (toInt (pred (fromInt 10))) => 9 +("toStr") = (toStr zero) => "λf.λn.(n)" +("toStr") = (toStr one) => "λf.λn.(f(n))" +("toStr") = (toStr two) => "λf.λn.(f(f(n)))" +("toStr") = (toStr (succ (succ (succ zero)))) => "λf.λn.(f(f(f(n))))" +("toStr") = (toStr (fromInt 5)) => "λf.λn.(f(f(f(f(f(n))))))" + +Testing booleans-test +("true") = (toBoolean T) => true +("false") = (toBoolean F) => false +("If") = (toBoolean (((If T) T) F)) => true +("If") = (toBoolean (((If F) T) F)) => false +("And") = (toBoolean ((And T) T)) => true +("And") = (toBoolean ((And T) F)) => false +("And") = (toBoolean ((And F) T)) => false +("And") = (toBoolean ((And F) F)) => false +("And") = (toBoolean ((And T) ((And T) T))) => true +("And") = (toBoolean ((And T) ((And F) T))) => false +("Or") = (toBoolean ((Or T) T)) => true +("Or") = (toBoolean ((Or T) F)) => true +("Or") = (toBoolean ((Or F) T)) => true +("Or") = (toBoolean ((Or F) F)) => false +("Or") = (toBoolean ((Or F) ((Or F) F))) => false +("Or") = (toBoolean ((Or F) ((Or T) F))) => true +("Not") = (toBoolean (Not T)) => false +("Not") = (toBoolean (Not F)) => true +("Not") = (toBoolean (Not (Not T))) => true +("Not") = (toBoolean (Not (Not F))) => false +("Xor") = (toBoolean ((Xor T) T)) => false +("Xor") = (toBoolean ((Xor T) F)) => true +("Xor") = (toBoolean ((Xor F) T)) => true +("Xor") = (toBoolean ((Xor F) F)) => false +("Expressions") = (toBoolean ((And T) ((And T) ((Or F) T)))) => true +("Expressions") = (toBoolean ((And T) ((And F) ((Or F) ((And T) T))))) => false +("Expressions") = (toBoolean ((Or T) ((And F) ((Or F) ((And T) T))))) => true +("Expressions") = (toBoolean ((Or F) ((And F) ((Or F) ((And F) T))))) => false +("Expressions") = (toBoolean ((And ((Or F) F)) ((And T) ((Or F) T)))) => false +("Expressions") = (toBoolean ((And ((Or T) F)) ((And T) ((Or F) T)))) => true + +Testing combinators-test +("Z-factorial") = (toInt (Z-factorial (fromInt 9) one)) => 362880 +("Y-factorial") = (toInt (Y-factorial (fromInt 9) one)) => 362880 + +Ran 7 tests containing 56 assertions. +0 failures, 0 errors.