From 2059b41f338ddd921d45a861fe320e03a292836c Mon Sep 17 00:00:00 2001 From: Radek Szymanski Date: Sat, 24 Jan 2026 18:00:22 +0100 Subject: [PATCH] Add Janet brainfuck test --- README.md | 1 + brainfuck/Makefile | 6 ++- brainfuck/bf.janet | 110 +++++++++++++++++++++++++++++++++++++++++++++ common/commands.mk | 1 + docker/Dockerfile | 7 +++ docker/versions.rb | 1 + 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100755 brainfuck/bf.janet diff --git a/README.md b/README.md index 9a6d60d4..cd444b39 100644 --- a/README.md +++ b/README.md @@ -441,6 +441,7 @@ Base Docker image: Debian GNU/Linux trixie/sid | Go/gccgo | 14.2.0 | | Haskell | 9.10.2 | | Idris 2 | 0.7.0 | +| Janet | 1.40.1-1449ad8 | | Java | 24.0.2 | | Julia | v"1.11.6" | | Kotlin | 2.2.0 | diff --git a/brainfuck/Makefile b/brainfuck/Makefile index b6540664..bb21710f 100644 --- a/brainfuck/Makefile +++ b/brainfuck/Makefile @@ -59,7 +59,8 @@ all_runners := $(fast_runners) \ run[bf.lua] \ run[bf.tcl] \ run[bf_oo.tcl] \ - run[bf.php] + run[bf.php] \ + run[bf.janet] # Build @@ -243,6 +244,9 @@ run[bf.jl]:: run[%]: % | $(julia_fmt) run[bf.php]:: run[%]: % $(PHP_RUN) $(BF_SRC) +run[bf.janet]:: run[%]: % + $(JANET_RUN) $(BF_SRC) + # Utilities .PHONY: clean diff --git a/brainfuck/bf.janet b/brainfuck/bf.janet new file mode 100755 index 00000000..b38355b2 --- /dev/null +++ b/brainfuck/bf.janet @@ -0,0 +1,110 @@ +(def OP_INC 0) +(def OP_MOVE 1) +(def OP_LOOP 2) +(def OP_PRINT 3) + +(defn read-file [file-name] + (with [f (file/open file-name)] + (map string/from-bytes (file/read f :all)))) + +(defn parse-text [code & [pos]] + (var res @[]) + (var idx (or pos 0)) + (def len (length code)) + (label result + (while (< idx len) + (let [c (get code idx)] + (++ idx) + (case c + "+" (array/push res [OP_INC 1]) + "-" (array/push res [OP_INC -1]) + ">" (array/push res [OP_MOVE 1]) + "<" (array/push res [OP_MOVE -1]) + "." (array/push res [OP_PRINT 0]) + "[" (let [[sub-res sub-idx] (parse-text code idx)] + (array/push res [OP_LOOP sub-res]) + (set idx sub-idx)) + "]" (return result [res idx]) + nil)))) + [res idx]) + +(defn make-tape [] + @{:tape @[0] :pos 0}) + +(defn tape-get [tape] + (get (tape :tape) (tape :pos))) + +(defn tape-inc [tape x] + (let [t (tape :tape) + p (tape :pos)] + (+= (t p) x))) + +(defn tape-move [tape x] + (let [t (tape :tape) + len (length t)] + (+= (tape :pos) x) + (when (>= (tape :pos) len) + (array/join t (array/new-filled (* 2 len) 0))))) + +(defn make-printer [quiet] + @{:sum1 0 :sum2 0 :quiet quiet}) + +(defn tape-print [printer n] + (if (printer :quiet) + (do + (set (printer :sum1) + (% (+ (printer :sum1) n) 255)) + (set (printer :sum2) + (% (+ (printer :sum1) (printer :sum2)) 255))) + (do + (file/write stdout (string/from-bytes n)) + (file/flush stdout)))) + +(defn tape-checksum [printer] + (let [sum1 (printer :sum1) + sum2 (printer :sum2)] + (bor (blshift sum2 8) sum1))) + +(defn run [ops tape printer] + (each [op val] ops + (case op + OP_INC (tape-inc tape val) + OP_MOVE (tape-move tape val) + OP_LOOP (while (> (tape-get tape) 0) + (run val tape printer)) + OP_PRINT (tape-print printer (tape-get tape)) + nil))) + +(defn notify [msg] + (try + (with [s (net/connect "localhost" 9001)] + (net/write s msg)) + ([err] (eprint "Connection failed: " err)))) + +(defn verify [] + (def text "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.> + ---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.") + + (def p-left (make-printer true)) + (var tape (make-tape)) + (run (first (parse-text (map string/from-bytes text))) tape p-left) + (def left (tape-checksum p-left)) + + (def p-right (make-printer true)) + (each c "Hello World!\n" + (tape-print p-right c)) + (def right (tape-checksum p-right)) + (when (not= left right) + (eprintf "%d != %d" left right) + (os/exit 1))) + +(verify) +(def text (first (parse-text (read-file (get (dyn :args) 1))))) +(def printer (make-printer (not (empty? (or (os/getenv "QUIET") ""))))) + +(notify (string/format "Janet\t%d" (os/getpid))) +(run text (make-tape) printer) +(notify "stop") + +(when (printer :quiet) + (print "Output checksum: " (tape-checksum printer))) diff --git a/common/commands.mk b/common/commands.mk index e2534103..6cd3fed4 100644 --- a/common/commands.mk +++ b/common/commands.mk @@ -77,6 +77,7 @@ TRUBY_NATIVE_RUN = $(XTIME) truffleruby $^ SCHEME_RUN = $(XTIME) scheme --optimize-level 3 --program $^ JULIA_RUN = $(XTIME) julia --optimize=3 --check-bounds=no $^ PHP_RUN = $(XTIME) php $^ +JANET_RUN = $(XTIME) janet $^ GIT_CLONE = git clone --depth 1 -q DOTNET_CLEAN = -dotnet clean --nologo -v q -c Release diff --git a/docker/Dockerfile b/docker/Dockerfile index 8eb24fa6..fa716f42 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -310,6 +310,13 @@ RUN cabal update \ && cabal install hlint ENV GHC_PACKAGE_PATH="~/.cabal/store/ghc-${GHC_VER}/package.db:" +# https://github.com/janet-lang/janet/releases +ARG JANET=v1.40.1 +RUN curl -LO \ + https://github.com/janet-lang/janet/releases/download/$JANET/janet-$JANET-linux-x64.tar.gz \ + && tar xf janet-$JANET-linux-x64.tar.gz +ENV PATH="/root/bin/janet-$JANET-linux/bin/:${PATH}" + ARG SCRIPTS_VER=unknown COPY *.rb ./ diff --git a/docker/versions.rb b/docker/versions.rb index ffb69871..f6f8bb23 100755 --- a/docker/versions.rb +++ b/docker/versions.rb @@ -119,6 +119,7 @@ class Test { 'Idris 2' => -> { `idris2 --version`.split[-1] }, 'Odin' => -> { `odin version`.split[-1] }, 'C3' => -> { `c3c --version`.lines.first[/C3 Compiler Version:\s+(\d+\.\d+\.\d+)/, 1] }, + 'Janet' => -> { `janet --version` }, }.freeze def pad(num, str, padstr)