Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
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

Expand Down
20 changes: 14 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@ 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 (`<print>` header) — not on
- [x] **Step 2 — C++ and Go.** C++ needs GCC 14 (`<print>` 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.
- [ ] **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.
- [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.
- [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 && 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# 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;
Expand Down
2 changes: 2 additions & 0 deletions languages/c/c++/expected-output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
true
1
13 changes: 13 additions & 0 deletions languages/c/c++/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# C++23 <print> 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 <print>" >&2
exit 42
fi
"$CXX" lambda-core.cpp -std=c++23 -o lambda-core.test || exit 1
./lambda-core.test
status=$?
rm -f lambda-core.test
exit $status
65 changes: 65 additions & 0 deletions languages/c/clojure/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions languages/c/clojure/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# The Clojure impl is a deps.edn project with its own clojure.test runner.
# 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
30 changes: 30 additions & 0 deletions languages/e/elixir/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions languages/e/elixir/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
elixir lambda-core.exs
29 changes: 29 additions & 0 deletions languages/f/fsharp/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions languages/f/fsharp/test.sh
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions languages/g/go/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions languages/g/go/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go run .
16 changes: 16 additions & 0 deletions languages/h/haskell/expected-output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
True
False
False
True
False
False
False
True
False
True
True
True
0
1
1
0
1 change: 1 addition & 0 deletions languages/h/haskell/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
runghc lambda-core.hs
22 changes: 22 additions & 0 deletions languages/l/lua/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions languages/l/lua/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lua5.4 lambda-core.lua
30 changes: 30 additions & 0 deletions languages/o/ocaml/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions languages/o/ocaml/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ocaml lambda_core.ml
30 changes: 30 additions & 0 deletions languages/r/ruby/expected-output.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions languages/r/ruby/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ruby lambda-core.rb
Loading
Loading