From d4b1c8ecef7e406c2fdfe4e507c98841b501bcee Mon Sep 17 00:00:00 2001 From: Seong-Heon Jung Date: Thu, 2 Apr 2026 14:25:39 -0400 Subject: [PATCH 01/10] add simple examples to CI --- .github/workflows/examples.yml | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/examples.yml diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 000000000..e6a1b315c --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,68 @@ +name: Examples + +on: + push: + branches: [ "main" ] + paths: + - ".github/workflows/examples.yml" + - "examples/**" + - "basis-library/**" + - "mlton/**" + - "runtime/**" + - "include/**" + - "Makefile" + - "Makefile.config" + - "default.nix" + - "Dockerfile.amd64" + - "Dockerfile.arm64" + - "docker-bake.hcl" + pull_request: + branches: [ "main" ] + paths: + - ".github/workflows/examples.yml" + - "examples/**" + - "basis-library/**" + - "mlton/**" + - "runtime/**" + - "include/**" + - "Makefile" + - "Makefile.config" + - "default.nix" + - "Dockerfile.amd64" + - "Dockerfile.arm64" + - "docker-bake.hcl" + +jobs: + build-and-run-examples: + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y mlton libgmp-dev gcc make + + - name: Build MPL compiler + run: make --silent + + - name: Build examples + run: make -C examples --silent + + - name: Run examples smoke tests + run: | + set -euo pipefail + cd examples + + ./bin/fib -N 20 + ./bin/random -N 1000 -seed 1 + ./bin/primes -N 10000 + ./bin/msort -N 20000 + ./bin/dmm -N 16 + ./bin/ray -m 32 -n 32 -s rgbbox + ./bin/nn -N 500 + ./bin/nqueens -N 10 + ./bin/coins -N 100 -repeat 1 \ No newline at end of file From 1446988e65c1e8357c886e5048a582b7fa51ba4a Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:18:27 -0400 Subject: [PATCH 02/10] feat: correct outputs for examples --- examples/expected/coins.ok | 4 ++++ examples/expected/dmm.ok | 2 ++ examples/expected/fib.ok | 2 ++ examples/expected/msort.ok | 3 +++ examples/expected/nn.ok | 3 +++ examples/expected/nqueens.ok | 2 ++ examples/expected/primes.ok | 3 +++ examples/expected/random.ok | 3 +++ examples/expected/ray.ok | 3 +++ 9 files changed, 25 insertions(+) create mode 100644 examples/expected/coins.ok create mode 100644 examples/expected/dmm.ok create mode 100644 examples/expected/fib.ok create mode 100644 examples/expected/msort.ok create mode 100644 examples/expected/nn.ok create mode 100644 examples/expected/nqueens.ok create mode 100644 examples/expected/primes.ok create mode 100644 examples/expected/random.ok create mode 100644 examples/expected/ray.ok diff --git a/examples/expected/coins.ok b/examples/expected/coins.ok new file mode 100644 index 000000000..33bfbd375 --- /dev/null +++ b/examples/expected/coins.ok @@ -0,0 +1,4 @@ +N 100 +sequential? false +repeat 1 +Parallel: 243. diff --git a/examples/expected/dmm.ok b/examples/expected/dmm.ok new file mode 100644 index 000000000..ed7fba0a4 --- /dev/null +++ b/examples/expected/dmm.ok @@ -0,0 +1,2 @@ +generating matrices of sidelength 16 +multiplying diff --git a/examples/expected/fib.ok b/examples/expected/fib.ok new file mode 100644 index 000000000..cec1e45de --- /dev/null +++ b/examples/expected/fib.ok @@ -0,0 +1,2 @@ +fib 20 +result 6765 diff --git a/examples/expected/msort.ok b/examples/expected/msort.ok new file mode 100644 index 000000000..4e4ac83a2 --- /dev/null +++ b/examples/expected/msort.ok @@ -0,0 +1,3 @@ +generating 20000 random integers +sorting +result [1, 2, 3, 6, 6, 7, 8, ..., 19999] diff --git a/examples/expected/nn.ok b/examples/expected/nn.ok new file mode 100644 index 000000000..504ed01e3 --- /dev/null +++ b/examples/expected/nn.ok @@ -0,0 +1,3 @@ +N 500 +to see output, use -output and -resolution arguments +for example: nn -N 10000 -output result.ppm -resolution 1000 diff --git a/examples/expected/nqueens.ok b/examples/expected/nqueens.ok new file mode 100644 index 000000000..c36550330 --- /dev/null +++ b/examples/expected/nqueens.ok @@ -0,0 +1,2 @@ +counting number of 10x10 solutions +result 724 diff --git a/examples/expected/primes.ok b/examples/expected/primes.ok new file mode 100644 index 000000000..2285fffff --- /dev/null +++ b/examples/expected/primes.ok @@ -0,0 +1,3 @@ +generating primes up to 10000 +number of primes 1229 +result [2, 3, 5, 7, 11, 13, 17, ..., 9973] diff --git a/examples/expected/random.ok b/examples/expected/random.ok new file mode 100644 index 000000000..31fa590b7 --- /dev/null +++ b/examples/expected/random.ok @@ -0,0 +1,3 @@ +tabulate 1000 pseudo-random 64-bit words +seed 1 +result [AE5DE3C06E3E5C7A, 9B3DDF966C314FED, ..., D1BFFB87661C5706] diff --git a/examples/expected/ray.ok b/examples/expected/ray.ok new file mode 100644 index 000000000..051a452b8 --- /dev/null +++ b/examples/expected/ray.ok @@ -0,0 +1,3 @@ +Using scene 'rgbbox' (-s to switch). +Writing image to ray_result.ppm. +ray_result.ppm checksum: 032cf4f851743a2aca85dd662551330e From f26a8a382f23e83828d7f96b64dd3d077d9236c1 Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:18:44 -0400 Subject: [PATCH 03/10] chore: don't include the ray result --- examples/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/.gitignore b/examples/.gitignore index e660fd93d..e6d95573a 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1 +1,2 @@ bin/ +ray_result.ppm From 79ac80613f587714251e6bc7f7d8b28d5a5e3b02 Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:19:08 -0400 Subject: [PATCH 04/10] feat: strip timing, diff with expected --- .github/workflows/examples.yml | 55 ++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index e6a1b315c..cc51e27a8 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -57,12 +57,49 @@ jobs: set -euo pipefail cd examples - ./bin/fib -N 20 - ./bin/random -N 1000 -seed 1 - ./bin/primes -N 10000 - ./bin/msort -N 20000 - ./bin/dmm -N 16 - ./bin/ray -m 32 -n 32 -s rgbbox - ./bin/nn -N 500 - ./bin/nqueens -N 10 - ./bin/coins -N 100 -repeat 1 \ No newline at end of file + # Strip timing information from program output. + # Removes "finished in X.XXXXs" and similar timing substrings, + # then removes any resulting blank lines. + strip_timing() { + sed -E \ + -e 's/[Ff]inished in:? [0-9]+\.[0-9]+s\.?//g' \ + -e 's/Scene BVH construction in [0-9]+\.[0-9]+s\.?//g' \ + -e 's/Rendering in [0-9]+\.[0-9]+s\.?//g' \ + -e 's/generated input in [0-9]+\.[0-9]+s//g' \ + -e 's/built quadtree in [0-9]+\.[0-9]+s//g' \ + -e 's/found all neighbors in [0-9]+\.[0-9]+s//g' \ + -e 's/[[:space:]]+$//' \ + | sed '/^$/d' + } + + fail=0 + check_output() { + local name="$1" + shift + local actual + actual=$("$@" 2>&1 | strip_timing) + local expected + expected=$(cat "expected/${name}.ok") + if [ "$actual" != "$expected" ]; then + echo "FAIL: $name" + diff <(echo "$actual") <(echo "$expected") || true + fail=1 + else + echo "PASS: $name" + fi + } + + check_output fib ./bin/fib -N 20 + check_output random ./bin/random -N 1000 -seed 1 + check_output primes ./bin/primes -N 10000 + check_output msort ./bin/msort -N 20000 + check_output dmm ./bin/dmm -N 16 + check_output ray bash -c './bin/ray -m 32 -n 32 -s rgbbox -f ray_result.ppm && echo "ray_result.ppm checksum: $(md5sum ray_result.ppm | cut -d" " -f1)"' + check_output nn ./bin/nn -N 500 + check_output nqueens ./bin/nqueens -N 10 + check_output coins ./bin/coins -N 100 -repeat 1 + + if [ "$fail" -ne 0 ]; then + echo "Some output checks failed!" + exit 1 + fi \ No newline at end of file From 396cf405edf0d5c5c40528ab1fde172881ec879c Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:42:57 -0400 Subject: [PATCH 05/10] chore: actually output something from dmm --- examples/expected/dmm.ok | 1 + examples/src/dmm/main.sml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/examples/expected/dmm.ok b/examples/expected/dmm.ok index ed7fba0a4..90b5bb622 100644 --- a/examples/expected/dmm.ok +++ b/examples/expected/dmm.ok @@ -1,2 +1,3 @@ generating matrices of sidelength 16 multiplying +result [16.0, 16.0, 16.0, ..., 16.0] diff --git a/examples/src/dmm/main.sml b/examples/src/dmm/main.sml index e08e0a8cc..d353dede3 100644 --- a/examples/src/dmm/main.sml +++ b/examples/src/dmm/main.sml @@ -13,3 +13,6 @@ val _ = print ("multiplying\n") val (result, tm) = Util.getTime (fn _ => TreeMatrix.multiply (input, input)) val _ = print ("finished in " ^ Time.fmt 4 tm ^ "s\n") + +val flat = TreeMatrix.flatten result +val _ = print ("result " ^ Util.summarizeArray 4 (Real.fmt (StringCvt.FIX (SOME 1))) flat ^ "\n") From f6f1561c0d8900f60473b21cc950c03c9d9868fd Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:44:12 -0400 Subject: [PATCH 06/10] chore: more output from nn --- examples/expected/nn.ok | 4 ++++ examples/src/nn/main.sml | 1 + 2 files changed, 5 insertions(+) diff --git a/examples/expected/nn.ok b/examples/expected/nn.ok index 504ed01e3..1ee500feb 100644 --- a/examples/expected/nn.ok +++ b/examples/expected/nn.ok @@ -1,3 +1,7 @@ N 500 +generated input +built quadtree +found all neighbors +result [359, 396, 463, ..., 340] to see output, use -output and -resolution arguments for example: nn -N 10000 -output result.ppm -resolution 1000 diff --git a/examples/src/nn/main.sml b/examples/src/nn/main.sml index b792bb774..64f21f5e4 100644 --- a/examples/src/nn/main.sml +++ b/examples/src/nn/main.sml @@ -25,6 +25,7 @@ val _ = print ("built quadtree in " ^ Time.fmt 4 tm ^ "s\n") val (nbrs, tm) = Util.getTime (fn _ => NN.allNearestNeighbors grain tree) val _ = print ("found all neighbors in " ^ Time.fmt 4 tm ^ "s\n") +val _ = print ("result " ^ Util.summarizeArraySlice 4 Int.toString nbrs ^ "\n") (* now input[nbrs[i]] is the closest point to input[i] *) From 6eae440bc403da5b6f17370b74a89670d2650a73 Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:46:49 -0400 Subject: [PATCH 07/10] feat: more unstripped outputs and inputs for reverb, tokens, dedup --- examples/expected/dedup.ok | 8 ++++++++ examples/expected/input.txt | 2 ++ examples/expected/ray.ok | 2 ++ examples/expected/reverb.ok | 4 ++++ examples/expected/seam-carve.ok | 11 +++++++++++ examples/expected/test.wav | Bin 0 -> 8044 bytes examples/expected/tokens.ok | 15 +++++++++++++++ 7 files changed, 42 insertions(+) create mode 100644 examples/expected/dedup.ok create mode 100644 examples/expected/input.txt create mode 100644 examples/expected/reverb.ok create mode 100644 examples/expected/seam-carve.ok create mode 100644 examples/expected/test.wav create mode 100644 examples/expected/tokens.ok diff --git a/examples/expected/dedup.ok b/examples/expected/dedup.ok new file mode 100644 index 000000000..fbe956efa --- /dev/null +++ b/examples/expected/dedup.ok @@ -0,0 +1,8 @@ +brown +quick +jumps +lazy +the +fox +dog +over diff --git a/examples/expected/input.txt b/examples/expected/input.txt new file mode 100644 index 000000000..a1ac5c902 --- /dev/null +++ b/examples/expected/input.txt @@ -0,0 +1,2 @@ +the quick brown fox jumps over the lazy dog +the fox the fox the dog diff --git a/examples/expected/ray.ok b/examples/expected/ray.ok index 051a452b8..61444a1d6 100644 --- a/examples/expected/ray.ok +++ b/examples/expected/ray.ok @@ -1,3 +1,5 @@ Using scene 'rgbbox' (-s to switch). +Scene BVH construction +Rendering Writing image to ray_result.ppm. ray_result.ppm checksum: 032cf4f851743a2aca85dd662551330e diff --git a/examples/expected/reverb.ok b/examples/expected/reverb.ok new file mode 100644 index 000000000..8a4e9105a --- /dev/null +++ b/examples/expected/reverb.ok @@ -0,0 +1,4 @@ +read sound +reverberated +wrote output +reverb_result.wav checksum: 39c9c6c243f68588951d28c83a9b805e diff --git a/examples/expected/seam-carve.ok b/examples/expected/seam-carve.ok new file mode 100644 index 000000000..4447d2682 --- /dev/null +++ b/examples/expected/seam-carve.ok @@ -0,0 +1,11 @@ +block-width 80 +num-seams 5 +read image +height 32 +width 32 +seam carving... +computed seam carving index +remapped color palette +generated images +wrote to seam_result.gif +seam_result.gif checksum: 6e1699d1291f5e1b0438a5df4495575e diff --git a/examples/expected/test.wav b/examples/expected/test.wav new file mode 100644 index 0000000000000000000000000000000000000000..4a637cb873dcc3c8f137d69bc170742c182016f8 GIT binary patch literal 8044 zcmWIYbaP9QXJ80-40BD(Em06)U|?VbLIKV(K5?0!>im<-8xi4|<$^WwezM0Mr$)LEWMJo?&?Ih zrm2nB`=eJsy72pVuX?ecP|nMmKXu$i^TMwhadLRyIl4t<8hgv+27{jZrHv=Qe!e3A z(Y-hQW!1j=ic-H=X)7)P(I?rv@6K{<6KeS1@o#?kq2I56i>o`%Ps*+MU!PksKS|y3 zxA^bZ;fMas|KB0h;M#U~R`zbuCtL#3R(`P+rTgk%R`sTTbiX41^>gFN`lSXvlN;Du zRHhx>;(dpc>+{j})oA-_w7omp{}}CmjP?gd`{$$m^U?8=(eaYe@vG7C#L@A@ g(ed5U@%GX2_R;x|(fO#+`KZzP!O{8Jftjxb0Bg>8qyPW_ literal 0 HcmV?d00001 diff --git a/examples/expected/tokens.ok b/examples/expected/tokens.ok new file mode 100644 index 000000000..15dd77153 --- /dev/null +++ b/examples/expected/tokens.ok @@ -0,0 +1,15 @@ +the +quick +brown +fox +jumps +over +the +lazy +dog +the +fox +the +fox +the +dog From 90d2180b085cdf06ef9c46f464b88c3d4dd96d26 Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:47:16 -0400 Subject: [PATCH 08/10] chore: don't include new results --- examples/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/.gitignore b/examples/.gitignore index e6d95573a..ea8b35d84 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,2 +1,4 @@ bin/ ray_result.ppm +seam_result.gif +reverb_result.wav From a91256af7625352404d672e97cba2af001e19df6 Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:47:40 -0400 Subject: [PATCH 09/10] chore: add support for remaining examples --- .github/workflows/examples.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index cc51e27a8..cd052af0a 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -58,16 +58,12 @@ jobs: cd examples # Strip timing information from program output. - # Removes "finished in X.XXXXs" and similar timing substrings, + # Removes "... in X.XXXXs" and "Finished in: X.XXXXs" substrings, # then removes any resulting blank lines. strip_timing() { sed -E \ -e 's/[Ff]inished in:? [0-9]+\.[0-9]+s\.?//g' \ - -e 's/Scene BVH construction in [0-9]+\.[0-9]+s\.?//g' \ - -e 's/Rendering in [0-9]+\.[0-9]+s\.?//g' \ - -e 's/generated input in [0-9]+\.[0-9]+s//g' \ - -e 's/built quadtree in [0-9]+\.[0-9]+s//g' \ - -e 's/found all neighbors in [0-9]+\.[0-9]+s//g' \ + -e 's/ in [0-9]+\.[0-9]+s\.?//g' \ -e 's/[[:space:]]+$//' \ | sed '/^$/d' } @@ -98,6 +94,10 @@ jobs: check_output nn ./bin/nn -N 500 check_output nqueens ./bin/nqueens -N 10 check_output coins ./bin/coins -N 100 -repeat 1 + check_output tokens ./bin/tokens expected/input.txt + check_output dedup ./bin/dedup expected/input.txt + check_output seam-carve bash -c './bin/seam-carve ray_result.ppm -num-seams 5 -output seam_result.gif && echo "seam_result.gif checksum: $(md5sum seam_result.gif | cut -d" " -f1)"' + check_output reverb bash -c './bin/reverb expected/test.wav -output reverb_result.wav && echo "reverb_result.wav checksum: $(md5sum reverb_result.wav | cut -d" " -f1)"' if [ "$fail" -ne 0 ]; then echo "Some output checks failed!" From f29c44b87d62842654ac1a16175ed99f2a5b30d5 Mon Sep 17 00:00:00 2001 From: Sundara Vishnu Satish Date: Thu, 2 Apr 2026 15:52:27 -0400 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20hopefully=20cache=20mpl=20builds?= =?UTF-8?q?=20=F0=9F=99=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/examples.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index cd052af0a..df04c3389 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -46,7 +46,15 @@ jobs: sudo apt-get update sudo apt-get install -y mlton libgmp-dev gcc make + - name: Cache MPL compiler + id: cache-mpl + uses: actions/cache@v4 + with: + path: build + key: mpl-${{ runner.os }}-${{ hashFiles('mlton/**', 'runtime/**', 'include/**', 'basis-library/**', 'Makefile', 'Makefile.config') }} + - name: Build MPL compiler + if: steps.cache-mpl.outputs.cache-hit != 'true' run: make --silent - name: Build examples