├── bun
├── tak.js
├── version.sh
└── run.sh
├── deno
├── tak.js
├── version.sh
└── run.sh
├── luajit
├── tak.lua
├── run.sh
└── version.sh
├── pypy
├── tak.py
├── run.sh
└── version.sh
├── c
├── run.sh
├── build.sh
├── version.sh
└── tak.c
├── v
├── run.sh
├── version.sh
├── build.sh
└── tak.v
├── c3
├── run.sh
├── build.sh
├── version.sh
└── tak.c3
├── codon
├── run.sh
├── version.sh
├── build.sh
└── tak.py
├── csharp
├── run.sh
├── build.sh
├── version.sh
├── tak.csproj
└── tak.cs
├── dlang
├── run.sh
├── build.sh
├── version.sh
└── tak.d
├── fortran
├── run.sh
├── build.sh
├── version.sh
└── tak.f90
├── go
├── build.sh
├── run.sh
├── version.sh
└── tak.go
├── java
├── build.sh
├── run.sh
├── version.sh
└── tak.java
├── oak
├── version.sh
├── run.sh
└── tak.oak
├── odin
├── run.sh
├── version.sh
├── build.sh
└── tak.odin
├── zig
├── run.sh
├── version.sh
├── build.sh
└── tak.zig
├── callisto
├── run.sh
├── version.sh
├── build.sh
└── tak.cal
├── chicken
├── run.sh
├── build.sh
├── version.sh
└── tak.scm
├── haskell
├── build.sh
├── run.sh
├── version.sh
└── tak.hs
├── lua
├── run.sh
├── version.sh
└── tak.lua
├── nodejs
├── run.sh
├── version.sh
└── tak.js
├── ocaml
├── run.sh
├── version.sh
├── build.sh
└── tak.ml
├── perl
├── run.sh
├── version.sh
└── tak.pl
├── quickjs
├── run.sh
├── version.sh
└── tak.js
├── r
├── run.sh
├── version.sh
└── tak.R
├── ruby
├── run.sh
├── version.sh
└── tak.rb
├── rust
├── run.sh
├── version.sh
├── build.sh
└── tak.rs
├── uxntal
├── version.sh
├── run.sh
├── uxnasm.rom
├── build.sh
├── tak.tal
└── uxnmin.c
├── arturo
├── version.sh
├── run.sh
└── tak.art
├── clojure
├── version.sh
├── run.sh
└── tak.clj
├── cython
├── version.sh
├── build.sh
├── run.sh
├── setup.py
└── tak.pyx
├── gforth
├── run.sh
├── version.sh
└── tak.fs
├── numba
├── run.sh
├── version.sh
└── tak.py
├── python
├── run.sh
├── version.sh
└── tak.py
├── lbforth
├── build.sh
├── version.sh
├── run.sh
├── tak.fs
└── lbForth.c
├── raku
├── run.sh
├── version.sh
└── tak.raku
├── wren
├── version.sh
├── run.sh
└── tak.wren
├── factor
├── run.sh
├── version.sh
└── tak.factor
├── .gitignore
├── missing
├── LICENSE.md
├── README.md
└── bench
/bun/tak.js:
--------------------------------------------------------------------------------
1 | ../nodejs/tak.js
--------------------------------------------------------------------------------
/deno/tak.js:
--------------------------------------------------------------------------------
1 | ../nodejs/tak.js
--------------------------------------------------------------------------------
/luajit/tak.lua:
--------------------------------------------------------------------------------
1 | ../lua/tak.lua
--------------------------------------------------------------------------------
/pypy/tak.py:
--------------------------------------------------------------------------------
1 | ../python/tak.py
--------------------------------------------------------------------------------
/bun/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | bun -v
3 |
--------------------------------------------------------------------------------
/c/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/deno/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | deno -v
3 |
--------------------------------------------------------------------------------
/v/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/v/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | v version
3 |
--------------------------------------------------------------------------------
/bun/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | bun tak.js $1 $2 $3
3 |
--------------------------------------------------------------------------------
/c3/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/codon/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/csharp/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/dlang/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/fortran/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/go/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | go build tak.go
3 |
--------------------------------------------------------------------------------
/go/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/go/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | go version
3 |
--------------------------------------------------------------------------------
/java/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | javac tak.java
3 |
--------------------------------------------------------------------------------
/oak/version.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | oak version
3 |
--------------------------------------------------------------------------------
/odin/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/odin/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | odin version
3 |
--------------------------------------------------------------------------------
/v/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | v -prod tak.v
3 |
--------------------------------------------------------------------------------
/zig/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/zig/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | zig version
3 |
--------------------------------------------------------------------------------
/c/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | gcc -O3 tak.c -o tak
3 |
--------------------------------------------------------------------------------
/callisto/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/chicken/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/codon/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | codon --version
3 |
--------------------------------------------------------------------------------
/deno/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | deno tak.js $1 $2 $3
3 |
--------------------------------------------------------------------------------
/dlang/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ldc2 tak.d -of=tak
3 |
--------------------------------------------------------------------------------
/haskell/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ghc -O tak.hs
3 |
--------------------------------------------------------------------------------
/haskell/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/haskell/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ghc --version
3 |
--------------------------------------------------------------------------------
/java/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | java Tak $1 $2 $3
3 |
--------------------------------------------------------------------------------
/lua/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | lua tak.lua $1 $2 $3
3 |
--------------------------------------------------------------------------------
/nodejs/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | node tak.js $1 $2 $3
3 |
--------------------------------------------------------------------------------
/nodejs/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | node --version
3 |
--------------------------------------------------------------------------------
/ocaml/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak.exe $1 $2 $3
3 |
--------------------------------------------------------------------------------
/ocaml/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ocamlc --version
3 |
--------------------------------------------------------------------------------
/perl/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | perl tak.pl $1 $2 $3
3 |
--------------------------------------------------------------------------------
/pypy/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | pypy3 tak.py $1 $2 $3
3 |
--------------------------------------------------------------------------------
/quickjs/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | qjs tak.js $1 $2 $3
3 |
--------------------------------------------------------------------------------
/r/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | Rscript tak.R $1 $2 $3
3 |
--------------------------------------------------------------------------------
/ruby/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ruby tak.rb $1 $2 $3
3 |
--------------------------------------------------------------------------------
/ruby/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ruby --version
3 |
--------------------------------------------------------------------------------
/rust/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./tak "$1" "$2" "$3"
3 |
--------------------------------------------------------------------------------
/rust/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rustc --version
3 |
--------------------------------------------------------------------------------
/uxntal/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | echo uxnmin.c
3 |
--------------------------------------------------------------------------------
/arturo/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | arturo --version
3 |
--------------------------------------------------------------------------------
/c/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | gcc --version | head -n 1
3 |
--------------------------------------------------------------------------------
/c3/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | c3c compile -O3 -g0 tak.c3
3 |
--------------------------------------------------------------------------------
/clojure/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | clojure --version
3 |
--------------------------------------------------------------------------------
/csharp/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | dotnet publish -o .
3 |
--------------------------------------------------------------------------------
/csharp/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | dotnet --version
3 |
--------------------------------------------------------------------------------
/cython/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cython --version
3 |
--------------------------------------------------------------------------------
/fortran/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | gfortran -o tak tak.f90
3 |
--------------------------------------------------------------------------------
/gforth/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | gforth tak.fs $3 $2 $1
3 |
--------------------------------------------------------------------------------
/gforth/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | gforth --version
3 |
--------------------------------------------------------------------------------
/luajit/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | luajit tak.lua $1 $2 $3
3 |
--------------------------------------------------------------------------------
/numba/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | python3 tak.py $1 $2 $3
3 |
--------------------------------------------------------------------------------
/oak/run.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | oak tak.oak $1 $2 $3
3 |
4 |
--------------------------------------------------------------------------------
/python/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | python3 tak.py $1 $2 $3
3 |
--------------------------------------------------------------------------------
/python/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | python --version
3 |
--------------------------------------------------------------------------------
/r/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | R --version | head -1
3 |
--------------------------------------------------------------------------------
/arturo/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | arturo tak.art $1 $2 $3
3 |
4 |
--------------------------------------------------------------------------------
/c3/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | c3c --version | head -n 1
3 |
--------------------------------------------------------------------------------
/clojure/run.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | clojure -M tak.clj $1 $2 $3
3 |
--------------------------------------------------------------------------------
/codon/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | codon build -release tak.py
3 |
--------------------------------------------------------------------------------
/java/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | java --version | head -n 1
3 |
--------------------------------------------------------------------------------
/lbforth/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | gcc -O3 lbForth.c -o lbforth
3 |
--------------------------------------------------------------------------------
/lua/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | lua -v | sed "s/ Copy.*//"
3 |
--------------------------------------------------------------------------------
/rust/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rustc -Copt-level=3 tak.rs
3 |
--------------------------------------------------------------------------------
/uxntal/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./uxnmin tak.rom $3 $2 $1
3 |
--------------------------------------------------------------------------------
/fortran/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | gfortran --version | head -n 1
3 |
--------------------------------------------------------------------------------
/luajit/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | luajit -v | sed "s/ --.*//"
3 |
--------------------------------------------------------------------------------
/odin/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | odin build tak.odin -file -o:speed
3 |
--------------------------------------------------------------------------------
/pypy/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | pypy3 --version | sed -n '2p'
3 |
--------------------------------------------------------------------------------
/raku/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | raku --optimize=3 tak.raku $1 $2 $3
3 |
--------------------------------------------------------------------------------
/zig/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | zig build-exe tak.zig -OReleaseFast
3 |
--------------------------------------------------------------------------------
/callisto/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cac --version | tr "\n" " "
3 | echo
4 |
--------------------------------------------------------------------------------
/cython/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | python setup.py build_ext --inplace
3 |
4 |
--------------------------------------------------------------------------------
/dlang/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ldc2 --version | head -n 1 | sed "s/:$//"
3 |
--------------------------------------------------------------------------------
/raku/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | raku -v | sed -n 's/.*\(Rakudo.*\)/\1/p'
3 |
--------------------------------------------------------------------------------
/cython/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | python -c "import tak; tak.main()" $1 $2 $3
3 |
4 |
--------------------------------------------------------------------------------
/uxntal/uxnasm.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/soxfox42/tak/HEAD/uxntal/uxnasm.rom
--------------------------------------------------------------------------------
/callisto/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cac -i ~/.local/lib/callisto-std -o tak tak.cal
3 |
--------------------------------------------------------------------------------
/ocaml/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Yes, .exe on Linux.
3 | ocamlc -o tak.exe tak.ml
4 |
--------------------------------------------------------------------------------
/perl/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # perl -v is annoying to parse
3 | perl -E "say \$^V"
4 |
--------------------------------------------------------------------------------
/lbforth/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "https://gist.github.com/lbruder/10007431 (RSTACK_SIZE 100)"
3 |
--------------------------------------------------------------------------------
/quickjs/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # qjs seems to have no version option
3 | qjs --help | head -n 1
4 |
--------------------------------------------------------------------------------
/lbforth/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | { cat tak.fs; echo "$3 $2 $1 tak ."; echo bye; } | ./lbforth | grep -o '[0-9]\+'
3 |
--------------------------------------------------------------------------------
/numba/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | python3 --version | tr -d '\n'
3 | echo -n ", Numba "
4 | pip show numba | grep Version:
5 |
--------------------------------------------------------------------------------
/uxntal/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cc -DNDEBUG -O2 -g0 -s uxnmin.c -lutil -o uxnmin
4 | cat tak.tal | ./uxnmin uxnasm.rom > tak.rom
5 |
--------------------------------------------------------------------------------
/wren/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | if command -v wren_cli > /dev/null; then
3 | wren=wren_cli
4 | else
5 | wren=wren
6 | fi
7 | $wren --version
8 |
--------------------------------------------------------------------------------
/wren/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | if command -v wren_cli > /dev/null; then
3 | wren=wren_cli
4 | else
5 | wren=wren
6 | fi
7 | $wren tak.wren $1 $2 $3
8 |
--------------------------------------------------------------------------------
/cython/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 | from Cython.Build import cythonize
3 |
4 | setup(
5 | ext_modules=cythonize("tak.pyx"),
6 | )
7 |
8 |
--------------------------------------------------------------------------------
/chicken/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if command -v chicken-csc > /dev/null; then
3 | chicken=chicken-csc
4 | else
5 | chicken=csc
6 | fi
7 | $chicken tak.scm
8 |
--------------------------------------------------------------------------------
/chicken/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if command -v chicken-csc > /dev/null; then
3 | chicken=chicken-csc
4 | else
5 | chicken=csc
6 | fi
7 | $chicken -release
8 |
--------------------------------------------------------------------------------
/factor/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if command -v factor-vm > /dev/null; then
3 | factor=factor-vm
4 | else
5 | factor=factor
6 | fi
7 | $factor tak.factor $3 $2 $1
8 |
--------------------------------------------------------------------------------
/factor/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if command -v factor-vm > /dev/null; then
3 | factor=factor-vm
4 | else
5 | factor=factor
6 | fi
7 | $factor --version | head -n 1
8 |
--------------------------------------------------------------------------------
/lbforth/tak.fs:
--------------------------------------------------------------------------------
1 | : 3dup dup 2over rot ;
2 | : -rot rot rot ;
3 | : tak 2dup >= if 2drop exit then 3dup 1- recurse >r 3dup -rot 1- recurse >r rot 1- recurse r> r> recurse ;
4 |
5 |
--------------------------------------------------------------------------------
/arturo/tak.art:
--------------------------------------------------------------------------------
1 | tak: function[x, y, z][
2 | (y < x)? -> tak tak x - 1 y z
3 | tak y - 1 z x
4 | tak z - 1 x y
5 | -> z
6 | ]
7 |
8 | print tak to :integer arg\0 to :integer arg\1 to :integer arg\2
9 |
10 |
--------------------------------------------------------------------------------
/perl/tak.pl:
--------------------------------------------------------------------------------
1 | use v5.34;
2 |
3 | sub tak {
4 | my ($x, $y, $z) = @_;
5 | return tak(
6 | tak($x - 1, $y, $z),
7 | tak($y - 1, $z, $x),
8 | tak($z - 1, $x, $y),
9 | ) if $y < $x;
10 | return $z;
11 | }
12 |
13 | my ($x, $y, $z) = @ARGV;
14 | say tak($x, $y, $z);
15 |
--------------------------------------------------------------------------------
/raku/tak.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 |
3 | sub tak(Int $x, Int $y, Int $z) {
4 | return tak(
5 | tak($x - 1, $y, $z),
6 | tak($y - 1, $z, $x),
7 | tak($z - 1, $x, $y),
8 | ) if $y < $x;
9 | return $z;
10 | }
11 |
12 | sub MAIN($x, $y, $z) {
13 | say tak($x, $y, $z);
14 | }
15 |
--------------------------------------------------------------------------------
/ruby/tak.rb:
--------------------------------------------------------------------------------
1 | def tak(x, y, z)
2 | if y < x
3 | tak(
4 | tak(x - 1, y, z),
5 | tak(y - 1, z, x),
6 | tak(z - 1, x, y),
7 | )
8 | else
9 | z
10 | end
11 | end
12 |
13 | x, y, z = ARGV.map(&:to_i)
14 | puts tak(x, y, z)
15 |
--------------------------------------------------------------------------------
/oak/tak.oak:
--------------------------------------------------------------------------------
1 | { println: println } := import('std')
2 |
3 |
4 | fn tak(x, y, z) if y < x {
5 | true -> tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
6 | _ -> z
7 | }
8 |
9 | [_, _, x, y, z] := args()
10 | x := int(x)
11 | y := int(y)
12 | z := int(z)
13 |
14 | println(tak(x, y, z))
15 |
16 |
--------------------------------------------------------------------------------
/chicken/tak.scm:
--------------------------------------------------------------------------------
1 | (import (chicken process-context))
2 |
3 | (define (tak x y z)
4 | (if (< y x)
5 | (tak
6 | (tak (- x 1) y z)
7 | (tak (- y 1) z x)
8 | (tak (- z 1) x y))
9 | z))
10 |
11 | (display (apply tak (map string->number (command-line-arguments))))
12 | (newline)
13 |
--------------------------------------------------------------------------------
/haskell/tak.hs:
--------------------------------------------------------------------------------
1 | import System.Environment
2 |
3 | tak :: Int -> Int -> Int -> Int
4 | tak x y z
5 | | y < x = tak
6 | (tak (x - 1) y z)
7 | (tak (y - 1) z x)
8 | (tak (z - 1) x y)
9 | | otherwise = z
10 |
11 | main :: IO ()
12 | main = do
13 | args <- getArgs
14 | let [x, y, z] = map read args :: [Int]
15 | print $ tak x y z
16 |
--------------------------------------------------------------------------------
/gforth/tak.fs:
--------------------------------------------------------------------------------
1 | : 3dup dup 2over rot ;
2 |
3 | : tak ( z y x -- n )
4 | 2dup >= if 2drop exit then
5 | 3dup 1- recurse >r
6 | 3dup -rot 1- recurse >r
7 | rot 1- recurse r> r>
8 | recurse ;
9 |
10 | : num-arg ( -- n )
11 | next-arg 2dup or 0= throw
12 | s>number? 0= throw drop ;
13 |
14 | num-arg num-arg num-arg tak . cr bye
15 |
--------------------------------------------------------------------------------
/r/tak.R:
--------------------------------------------------------------------------------
1 | args <- commandArgs(trailingOnly = TRUE)
2 |
3 | tak <- function(x, y, z) {
4 | if (y < x) {
5 | return(
6 | tak(
7 | tak(x - 1, y, z),
8 | tak(y - 1, z, x),
9 | tak(z - 1, x, y)
10 | )
11 | )
12 | }
13 | z
14 | }
15 |
16 | tak(as.numeric(args[1]), as.numeric(args[2]), as.numeric(args[3]))
17 |
--------------------------------------------------------------------------------
/codon/tak.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def tak(x, y, z):
5 | if y < x:
6 | return tak(
7 | tak(x - 1, y, z),
8 | tak(y - 1, z, x),
9 | tak(z - 1, x, y),
10 | )
11 | else:
12 | return z
13 |
14 |
15 | x, y, z = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
16 | print(tak(x, y, z))
17 |
--------------------------------------------------------------------------------
/python/tak.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def tak(x, y, z):
5 | if y < x:
6 | return tak(
7 | tak(x - 1, y, z),
8 | tak(y - 1, z, x),
9 | tak(z - 1, x, y),
10 | )
11 | else:
12 | return z
13 |
14 |
15 | x, y, z = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
16 | print(tak(x, y, z))
17 |
--------------------------------------------------------------------------------
/ocaml/tak.ml:
--------------------------------------------------------------------------------
1 | let rec tak x y z =
2 | if y < x then
3 | tak (tak (x - 1) y z)
4 | (tak (y - 1) z x)
5 | (tak (z - 1) x y)
6 | else
7 | z
8 |
9 | let () =
10 | let x = int_of_string Sys.argv.(1)
11 | and y = int_of_string Sys.argv.(2)
12 | and z = int_of_string Sys.argv.(3) in
13 | print_int (tak x y z);
14 | print_newline ()
15 |
16 |
--------------------------------------------------------------------------------
/csharp/tak.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net8.0
5 | enable
6 | enable
7 | true
8 | true
9 |
10 |
11 |
--------------------------------------------------------------------------------
/lua/tak.lua:
--------------------------------------------------------------------------------
1 | local function tak(x, y, z)
2 | if y < x then
3 | return tak(
4 | tak(x - 1, y, z),
5 | tak(y - 1, z, x),
6 | tak(z - 1, x, y)
7 | )
8 | end
9 | return z
10 | end
11 |
12 | local args = {...}
13 | local x = tonumber(args[1])
14 | local y = tonumber(args[2])
15 | local z = tonumber(args[3])
16 | print(tak(x, y, z))
17 |
--------------------------------------------------------------------------------
/numba/tak.py:
--------------------------------------------------------------------------------
1 | from numba import jit
2 | import sys
3 |
4 |
5 | @jit
6 | def tak(x, y, z):
7 | if y < x:
8 | return tak(
9 | tak(x - 1, y, z),
10 | tak(y - 1, z, x),
11 | tak(z - 1, x, y),
12 | )
13 | else:
14 | return z
15 |
16 |
17 | x, y, z = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
18 | print(tak(x, y, z))
19 |
--------------------------------------------------------------------------------
/nodejs/tak.js:
--------------------------------------------------------------------------------
1 | function tak(x, y, z) {
2 | if (y < x) {
3 | return tak(
4 | tak(x - 1, y, z),
5 | tak(y - 1, z, x),
6 | tak(z - 1, x, y)
7 | );
8 | } else {
9 | return z;
10 | }
11 | }
12 |
13 | // Get arguments from the command line
14 | const [x, y, z] = process.argv.slice(2).map(Number);
15 | console.log(tak(x, y, z));
16 |
17 |
--------------------------------------------------------------------------------
/quickjs/tak.js:
--------------------------------------------------------------------------------
1 | function tak(x, y, z) {
2 | if (y < x) {
3 | return tak(
4 | tak(x - 1, y, z),
5 | tak(y - 1, z, x),
6 | tak(z - 1, x, y)
7 | );
8 | } else {
9 | return z;
10 | }
11 | }
12 |
13 | // Get arguments from the command line
14 | const [_, x, y, z] = scriptArgs.map(Number);
15 |
16 | console.log(tak(x, y, z));
17 |
18 |
--------------------------------------------------------------------------------
/clojure/tak.clj:
--------------------------------------------------------------------------------
1 | (ns tak)
2 |
3 | (defn tak ^long [^long x ^long y ^long z]
4 | (if (< y x)
5 | (tak
6 | (tak (dec x) y z)
7 | (tak (dec y) z x)
8 | (tak (dec z) x y))
9 | z))
10 |
11 | (let [args *command-line-args*
12 | x (Long/parseLong (nth args 0))
13 | y (Long/parseLong (nth args 1))
14 | z (Long/parseLong (nth args 2))]
15 | (println (tak x y z)))
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Default to ignoring "tak"
2 | */tak
3 |
4 | csharp/bin
5 | csharp/obj
6 | csharp/tak.pdb
7 |
8 | cython/build
9 | cython/tak.c
10 | cython/tak.cpython*
11 |
12 | dlang/tak.o
13 |
14 | haskell/tak.hi
15 | haskell/tak.o
16 |
17 | java/Tak.class
18 |
19 | lbforth/lbforth
20 |
21 | ocaml/tak.cmi
22 | ocaml/tak.cmo
23 | ocaml/tak.exe
24 |
25 | uxntal/uxnmin
26 | uxntal/tak.rom*
27 |
28 | zig/tak.o
29 |
--------------------------------------------------------------------------------
/v/tak.v:
--------------------------------------------------------------------------------
1 | import os
2 | import strconv
3 |
4 | fn tak(x int, y int, z int) int {
5 | if y < x {
6 | return tak(
7 | tak(x - 1, y, z),
8 | tak(y - 1, z, x),
9 | tak(z - 1, x, y),
10 | )
11 | } else {
12 | return z
13 | }
14 | }
15 |
16 | fn main() {
17 | x := strconv.atoi(os.args[1])!
18 | y := strconv.atoi(os.args[2])!
19 | z := strconv.atoi(os.args[3])!
20 | println(tak(x, y, z))
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/c/tak.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int tak(int x, int y, int z) {
5 | if (y < x) {
6 | return tak(
7 | tak(x - 1, y, z),
8 | tak(y - 1, z, x),
9 | tak(z - 1, x, y)
10 | );
11 | }
12 | return z;
13 | }
14 |
15 | int main(int argc, char **argv) {
16 | int x = atoi(argv[1]), y = atoi(argv[2]), z = atoi(argv[3]);
17 | printf("%d\n", tak(x, y, z));
18 | }
19 |
--------------------------------------------------------------------------------
/go/tak.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strconv"
7 | )
8 |
9 | func tak(x, y, z int) int {
10 | if y < x {
11 | return tak(
12 | tak(x-1, y, z),
13 | tak(y-1, z, x),
14 | tak(z-1, x, y),
15 | )
16 | } else {
17 | return z
18 | }
19 | }
20 |
21 | func main() {
22 | x, _ := strconv.Atoi(os.Args[1])
23 | y, _ := strconv.Atoi(os.Args[2])
24 | z, _ := strconv.Atoi(os.Args[3])
25 | fmt.Printf("%d\n", tak(x, y, z))
26 | }
27 |
--------------------------------------------------------------------------------
/dlang/tak.d:
--------------------------------------------------------------------------------
1 | module tak.app;
2 |
3 | import std.conv;
4 | import std.stdio;
5 |
6 | int tak(int x, int y, int z) {
7 | if (y < x) {
8 | return tak(
9 | tak(x - 1, y, z),
10 | tak(y - 1, z, x),
11 | tak(z - 1, x, y)
12 | );
13 | }
14 | return z;
15 | }
16 |
17 |
18 | void main(string[] args) {
19 | writeln(tak(
20 | parse!int(args[1]),
21 | parse!int(args[2]),
22 | parse!int(args[3])
23 | ));
24 | }
25 |
--------------------------------------------------------------------------------
/rust/tak.rs:
--------------------------------------------------------------------------------
1 | use std::env;
2 |
3 | fn tak(x: i32, y: i32, z: i32) -> i32 {
4 | if y < x {
5 | return tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y));
6 | }
7 | z
8 | }
9 |
10 | fn main() {
11 | let args: Vec = env::args().collect();
12 |
13 | let x: i32 = args[1].parse().unwrap();
14 | let y: i32 = args[2].parse().unwrap();
15 | let z: i32 = args[3].parse().unwrap();
16 |
17 | println!("{}", tak(x, y, z));
18 | }
19 |
--------------------------------------------------------------------------------
/csharp/tak.cs:
--------------------------------------------------------------------------------
1 | class TakProgram
2 | {
3 | static int Tak(int x, int y, int z)
4 | {
5 | if (y < x)
6 | {
7 | return Tak(
8 | Tak(x - 1, y, z),
9 | Tak(y - 1, z, x),
10 | Tak(z - 1, x, y)
11 | );
12 | }
13 | else
14 | {
15 | return z;
16 | }
17 | }
18 |
19 | static void Main(string[] args)
20 | {
21 | int x = int.Parse(args[0]);
22 | int y = int.Parse(args[1]);
23 | int z = int.Parse(args[2]);
24 | Console.WriteLine(Tak(x, y, z));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/odin/tak.odin:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "core:fmt"
4 | import "core:os"
5 | import "core:strconv"
6 |
7 | tak :: proc(x, y, z: int) -> int {
8 | if y < x {
9 | return tak(
10 | tak(x - 1, y, z),
11 | tak(y - 1, z, x),
12 | tak(z - 1, x, y),
13 | )
14 | } else {
15 | return z
16 | }
17 | }
18 |
19 | main :: proc() {
20 | x, _ := strconv.parse_int(os.args[1])
21 | y, _ := strconv.parse_int(os.args[2])
22 | z, _ := strconv.parse_int(os.args[3])
23 | fmt.println(tak(x, y, z))
24 | }
25 |
--------------------------------------------------------------------------------
/c3/tak.c3:
--------------------------------------------------------------------------------
1 | import std::io;
2 |
3 | fn int tak(int x, int y, int z) {
4 | if (y < x) {
5 | return tak(
6 | tak(x - 1, y, z),
7 | tak(y - 1, z, x),
8 | tak(z - 1, x, y),
9 | );
10 | } else {
11 | return z;
12 | }
13 | }
14 |
15 | fn void main(String[] args) {
16 | int! x = args[1].to_int();
17 | int! y = args[2].to_int();
18 | int! z = args[3].to_int();
19 |
20 | if (try result = tak(x, y, z)) {
21 | io::printn(result);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/callisto/tak.cal:
--------------------------------------------------------------------------------
1 | include "cores/select.cal"
2 | include "std/args.cal"
3 | include "std/conv.cal"
4 | include "std/io.cal"
5 |
6 | func tak cell x cell y cell z -> cell n begin
7 | if y x < then
8 | x 1 - y z tak
9 | y 1 - z x tak
10 | z 1 - x y tak
11 | tak return
12 | else
13 | z return
14 | end
15 | end
16 |
17 | if get_args_length 4 < then
18 | 1 exit
19 | end
20 |
21 | let Array arg
22 |
23 | 1 &arg get_arg &arg parse_int
24 | 2 &arg get_arg &arg parse_int
25 | 3 &arg get_arg &arg parse_int
26 |
27 | tak printdec 10 printch
28 |
--------------------------------------------------------------------------------
/uxntal/tak.tal:
--------------------------------------------------------------------------------
1 | ( uxnmin tak.rom z y x )
2 |
3 | |10 @Console/vector $2 &read $5 &type $1 &write $1 &error $1
4 | |100
5 |
6 | @on-reset ( -> )
7 | ;on-console .Console/vector DEO2
8 | #00 BRK
9 |
10 | @on-console ( -> )
11 | .Console/type DEI #02 NEQk ?{
12 | POP2 #0a MUL .Console/read DEI #30 SUB ADD BRK }
13 | INC NEQk ?{ NEQ BRK }
14 | POP2 tak #0180 #0e DEO2 BRK
15 |
16 | @tak ( z y x -- res )
17 | LTHk ?{ POP2 JMP2r }
18 | ROT ROTk ROTk
19 | ( x-1 ) #01 SUB tak STH
20 | ( y-1 ) #01 SUB tak STH
21 | ( z-1 ) #01 SUB tak STHr STHr !tak
22 |
--------------------------------------------------------------------------------
/cython/tak.pyx:
--------------------------------------------------------------------------------
1 | # cython: boundscheck=False, wraparound=False
2 | import sys
3 | cimport cython
4 |
5 | @cython.cfunc
6 | @cython.locals(x=cython.int, y=cython.int, z=cython.int)
7 | def tak(x, y, z):
8 | if y < x:
9 | return tak(
10 | tak(x - 1, y, z),
11 | tak(y - 1, z, x),
12 | tak(z - 1, x, y),
13 | )
14 | else:
15 | return z
16 |
17 | def main():
18 | cdef int x, y, z
19 | x = int(sys.argv[1])
20 | y = int(sys.argv[2])
21 | z = int(sys.argv[3])
22 | print(tak(x, y, z))
23 |
24 |
--------------------------------------------------------------------------------
/wren/tak.wren:
--------------------------------------------------------------------------------
1 | import "os" for Process
2 |
3 | class Tak{
4 | static compute(x, y, z) {
5 | if (y < x) {
6 | return Tak.compute(
7 | Tak.compute(x - 1, y, z),
8 | Tak.compute(y - 1, z, x),
9 | Tak.compute(z - 1, x, y)
10 | )
11 | }
12 | return z
13 | }
14 | }
15 |
16 | var args = Process.arguments
17 |
18 | var x = Num.fromString(args[0])
19 | var y = Num.fromString(args[1])
20 | var z = Num.fromString(args[2])
21 |
22 | System.print(Tak.compute(x, y, z))
23 |
24 |
--------------------------------------------------------------------------------
/java/tak.java:
--------------------------------------------------------------------------------
1 | class Tak {
2 | static int tak(int x, int y, int z) {
3 | if (y < x) {
4 | return tak(
5 | tak(x - 1, y, z),
6 | tak(y - 1, z, x),
7 | tak(z - 1, x, y)
8 | );
9 | } else {
10 | return z;
11 | }
12 | }
13 |
14 | public static void main(String[] args) {
15 | int x = Integer.parseInt(args[0]);
16 | int y = Integer.parseInt(args[1]);
17 | int z = Integer.parseInt(args[2]);
18 |
19 | System.out.println(tak(x, y, z));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/factor/tak.factor:
--------------------------------------------------------------------------------
1 | ! from https://concatenative.org/wiki/view/Tak%20function
2 |
3 | USING:
4 | combinators.extras command-line generalizations
5 | kernel math math.parser namespaces prettyprint
6 | sequences ;
7 | IN: scratchpad
8 |
9 | ! patch this manually until fixed officially
10 | : 3tri* ( o s t u v w x y z p q r -- )
11 | [ 6 ndip ] 2dip [ 3dip ] dip call ; inline
12 | : 3tri@ ( r s t u v w x y z quot -- )
13 | dup dup 3tri* ; inline
14 |
15 | : tak ( z y x -- res )
16 | 2dup >= [ 2drop ] [
17 | rot 3dup rot 3dup rot [ 1 - tak ] 3tri@ tak
18 | ] if ;
19 |
20 | command-line get [ string>number ] map first3 tak .
21 |
--------------------------------------------------------------------------------
/zig/tak.zig:
--------------------------------------------------------------------------------
1 | const std = @import("std");
2 |
3 | fn tak(x: u32, y: u32, z: u32) u32 {
4 | if (y < x) {
5 | return tak(
6 | tak(x - 1, y, z),
7 | tak(y - 1, z, x),
8 | tak(z - 1, x, y),
9 | );
10 | } else {
11 | return z;
12 | }
13 | }
14 |
15 | pub fn main() !void {
16 | var buffer: [256]u8 = undefined;
17 | var fba = std.heap.FixedBufferAllocator.init(&buffer);
18 | const allocator = fba.allocator();
19 |
20 | const args = try std.process.argsAlloc(allocator);
21 | defer std.process.argsFree(allocator, args);
22 |
23 | const x = try std.fmt.parseInt(u32, args[1], 10);
24 | const y = try std.fmt.parseInt(u32, args[2], 10);
25 | const z = try std.fmt.parseInt(u32, args[3], 10);
26 |
27 | const stdout = std.io.getStdOut().writer();
28 | try stdout.print("{}\n", .{tak(x, y, z)});
29 | }
30 |
--------------------------------------------------------------------------------
/missing:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from pathlib import Path
4 |
5 | with open("README.md") as readme:
6 | lines = [line.strip() for line in readme]
7 |
8 | start = lines.index("") + 2
9 | end = lines.index("```", start)
10 |
11 | language_lines = lines[start:end]
12 | benched_languages = [line.split("|", 1)[0].strip() for line in language_lines]
13 |
14 | all_languages = []
15 |
16 | for path in Path.cwd().iterdir():
17 | run = path / "run.sh"
18 | if not run.exists():
19 | continue
20 | all_languages.append(path.name)
21 |
22 | missing_languages = set(all_languages) - set(benched_languages)
23 | extra_languages = set(benched_languages) - set(all_languages)
24 |
25 | if missing_languages:
26 | print("Missing languages:")
27 | for language in sorted(missing_languages):
28 | print(language)
29 | else:
30 | print("Everything looks good!")
31 |
32 | if extra_languages:
33 | print("Extra languages:")
34 | for language in sorted(extra_languages):
35 | print(language)
36 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2024 Finn Coffey
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
9 |
--------------------------------------------------------------------------------
/fortran/tak.f90:
--------------------------------------------------------------------------------
1 | program tak_program
2 | implicit none
3 | integer :: x, y, z, result
4 | character(len=10) :: arg1, arg2, arg3
5 |
6 | ! Get command line arguments as strings
7 | call get_command_argument(1, arg1)
8 | call get_command_argument(2, arg2)
9 | call get_command_argument(3, arg3)
10 |
11 | ! Convert the arguments to integers
12 | read(arg1, *) x
13 | read(arg2, *) y
14 | read(arg3, *) z
15 |
16 | ! Compute the result of the Tak function
17 | result = tak(x, y, z)
18 |
19 | ! Print the result without extra spaces
20 | print '(I0)', result
21 |
22 | contains
23 |
24 | recursive integer function tak(x, y, z) result(res)
25 | implicit none
26 | integer, intent(in) :: x, y, z
27 |
28 | if (y < x) then
29 | res = tak(tak(x - 1, y, z), &
30 | tak(y - 1, z, x), &
31 | tak(z - 1, x, y))
32 | else
33 | res = z
34 | end if
35 | end function tak
36 |
37 | end program tak_program
38 |
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tak
2 |
3 | > [!NOTE]
4 | > This project is mostly idle. I'm not adding any more implementations of my own for the time being. It's also not a very good benchmark, since all it really does is test an extremely recursive function.
5 | >
6 | > Feel free to submit PRs though, I'll get to them when I can, and update results accordingly :)
7 |
8 | [Tak](https://en.wikipedia.org/wiki/Tak_(function)) is a simple benchmark function. This repo contains some scripts I wrote to test various language implementations.
9 |
10 | It is defined as follows:
11 | ```py
12 | def tak(x, y, z):
13 | if y < x:
14 | return tak(
15 | tak(x - 1, y, z),
16 | tak(y - 1, z, x),
17 | tak(z - 1, x, y),
18 | )
19 | else:
20 | return z
21 | ```
22 |
23 | Current results - x = 48, y = 20, z = 12 - M1 MacBook Pro:
24 |
25 | ```
26 | c | 00:00.993648 | Apple clang version 16.0.0 (clang-1600.0.26.3)
27 | c3 | 00:00.993775 | C3 Compiler Version: 0.6.6
28 | rust | 00:00.994078 | rustc 1.81.0 (eeb90cda1 2024-09-04)
29 | zig | 00:00.994234 | 0.13.0
30 | v | 00:00.995175 | V 0.4.9 3953445
31 | codon | 00:00.996964 | 0.17.0
32 | csharp | 00:00.998090 | 8.0.108
33 | odin | 00:01.002665 | odin version dev-2025-01:2aae4cfd4
34 | java | 00:01.061346 | openjdk 21.0.3 2024-04-16 LTS
35 | go | 00:01.148092 | go version go1.23.2 darwin/arm64
36 | dlang | 00:01.394184 | LDC - the LLVM D compiler (1.39.0)
37 | clojure | 00:01.658746 | Clojure CLI version 1.12.3.1577
38 | numba | 00:01.999862 | Python 3.12.2, Numba Version: 0.60.0
39 | fortran | 00:02.268873 | GNU Fortran (Homebrew GCC 14.2.0_1) 14.2.0
40 | bun | 00:02.873798 | 1.2.0
41 | haskell | 00:02.950726 | The Glorious Glasgow Haskell Compilation System, version 9.8.2
42 | luajit | 00:03.192948 | LuaJIT 2.1.1727870382
43 | deno | 00:04.046599 | deno 2.1.7
44 | cython | 00:04.056156 | Cython version 3.0.11
45 | nodejs | 00:04.153770 | v23.3.0
46 | callisto | 00:05.339480 | The Glorious Callisto Compilation System Beta 0.11.1
47 | factor | 00:06.030762 | Factor 0.100 x86.64 (2281, heads/master-80a4633f05, Sep 11 2024 14:22:41)
48 | ocaml | 00:10.156417 | 5.2.0
49 | gforth | 00:13.504027 | gforth 0.7.3
50 | pypy | 00:14.293683 | [PyPy 7.3.17 with GCC Apple LLVM 15.0.0 (clang-1500.3.9.4)]
51 | uxntal | 00:14.654880 | uxnmin.c
52 | lua | 00:16.901724 | Lua 5.4.7
53 | chicken | 00:19.593212 | 5.4.0
54 | quickjs | 00:25.530629 | QuickJS version 2024-01-13
55 | wren | 00:27.523338 | wren 0.4.0
56 | ruby | 00:29.660727 | ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin24]
57 | python | 00:32.869780 | Python 3.12.2
58 | perl | 02:30.612512 | v5.34.1
59 | lbforth | 03:03.276468 | https://gist.github.com/lbruder/10007431 (RSTACK_SIZE 100)
60 | arturo | 04:23.373082 | arturo v/0.9.83
61 | raku | 04:38.605524 | Rakudo™ v2024.12.
62 | r | 05:49.101054 | R version 4.5.0 (2025-04-11) -- "How About a Twenty-Six"
63 | oak | 08:48.389520 | Oak v0.3
64 | ```
65 |
66 | Note that the Factor implementation was run via Rosetta 2 translation.
67 |
68 | Most natively compiled languages run about as fast as each other, any order between them is largely random noise.
69 |
70 | ## PRs Welcome!
71 |
72 | I'd love to build up a collection of more languages, and while I plan to implement some more myself, I won't say no to help!
73 |
74 | The general requirements for adding a new language:
75 | - Create a new folder for the language.
76 | - Add the implementation - usually named `tak.foo`, where `foo` is the relevant extension.
77 | - Add `run.sh`, which passes three arguments `$1`, `$2` and `$3` to the program.
78 | - Add `version.sh`, which should output the current version of the language. This should come directly from the interpreter/compiler, and be a single line of output. You can use common shell tools to process the output down to one line if necessary.
79 | - For compiled languages, add `build.sh` to generate the compiled output.
80 | - The program must read the values of x, y, and z from `argv`.
81 | - The program must produce some sort of output, as this makes verification and debugging easier.
82 | - The program must implement the Tak function as specified above - I'm interested in raw performance, not the number of clever optimisations you can make.
83 |
--------------------------------------------------------------------------------
/bench:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import argparse
4 | from datetime import datetime
5 | import datetime as dt
6 | from operator import itemgetter
7 | from pathlib import Path
8 | import subprocess
9 | import sys
10 |
11 | parser = argparse.ArgumentParser(description="Run the Tak benchmark")
12 | parser.add_argument(
13 | "-n",
14 | "--input",
15 | nargs=3,
16 | metavar=("X", "Y", "Z"),
17 | default=["48", "20", "12"],
18 | help="The input to the Tak function to use",
19 | )
20 | parser.add_argument(
21 | "-r",
22 | "--runs",
23 | type=int,
24 | default=4,
25 | help="The number of times to run each implementation",
26 | )
27 | parser.add_argument(
28 | "-i",
29 | "--impls",
30 | help="The implementations to run",
31 | )
32 | parser.add_argument(
33 | "-e",
34 | "--exclude",
35 | help="The implementations to skip running",
36 | )
37 | parser.add_argument(
38 | "-a",
39 | "--all",
40 | action="store_true",
41 | help="Run all implementations, including skipped-by-default ones",
42 | )
43 | parser.add_argument(
44 | "-t",
45 | "--timeout",
46 | type=int,
47 | default=180,
48 | help=(
49 | "The maximum total time to run each implementation for. "
50 | "Each implementation will be run at least once in full. "
51 | "Setting this to 0 will disable timeouts."
52 | ),
53 | )
54 | args = parser.parse_args()
55 |
56 | skip_default = [
57 | "arturo", # Very slow
58 | "callisto", # Requires building compiler and installing stdlib
59 | "lbforth", # Very slow
60 | "oak", # Very slow
61 | ]
62 |
63 | WARNING = "\x1b[33m"
64 | ERROR = "\x1b[31m"
65 | DIM = "\x1b[90m"
66 | RESET = "\x1b[0m"
67 |
68 | if args.impls and args.exclude:
69 | sys.exit(ERROR + "Error: --impls and --exclude cannot be used together" + RESET)
70 |
71 | impls = []
72 | exclude = args.exclude.split(",") if args.exclude else []
73 |
74 | if args.impls:
75 | # Explicitly specified
76 | for impl in args.impls.split(","):
77 | path = Path.cwd() / impl
78 | run = path / "run.sh"
79 | # Error if the user gave a bad impl name
80 | if not (path.exists() and run.exists()):
81 | sys.exit(f"{ERROR}Error: Implementation {impl} not found{RESET}")
82 | impls.append(path)
83 | else:
84 | for path in Path.cwd().iterdir():
85 | if not path.is_dir():
86 | continue
87 | run = path / "run.sh"
88 | if not run.exists():
89 | continue
90 | # Skip the tricky ones if -a is not passed
91 | if not args.all and path.name in skip_default:
92 | continue
93 | # Skip the ones the user asked to skip - even when -a is used
94 | if path.name in exclude:
95 | continue
96 | impls.append(path)
97 |
98 | impls.sort()
99 |
100 | results = []
101 |
102 | for path in impls:
103 | name = path.name
104 | version = path / "version.sh"
105 | build = path / "build.sh"
106 | run = path / "run.sh"
107 |
108 | print(f"{name}: ", end="", flush=True)
109 |
110 | version_output = "Unknown version"
111 | if version.exists():
112 | result = subprocess.run(
113 | version,
114 | cwd=path,
115 | stdout=subprocess.PIPE,
116 | stderr=subprocess.STDOUT,
117 | )
118 | if result.returncode == 0:
119 | version_output = result.stdout.decode("utf-8").strip()
120 | else:
121 | print(f"\n{WARNING}Warning: Failed to get {name} version{RESET}")
122 | else:
123 | print(f"\n{WARNING}Warning: Failed to get {name} version{RESET}")
124 |
125 | if build.exists():
126 | print("building", end="", flush=True)
127 | result = subprocess.run(
128 | build, cwd=path, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
129 | )
130 | if result.returncode != 0:
131 | print(f"\n{ERROR}Error: Failed to build {name}{RESET}")
132 | continue
133 | print(", ", end="")
134 |
135 | print("running", end="", flush=True)
136 |
137 | total = dt.timedelta()
138 | runs = 0
139 | ok = True
140 | for i in range(args.runs):
141 | start = datetime.now()
142 | result = subprocess.run(
143 | [run] + args.input,
144 | cwd=path,
145 | stdout=subprocess.DEVNULL,
146 | stderr=subprocess.DEVNULL,
147 | )
148 | if result.returncode != 0:
149 | print(f"\n{ERROR}Error: Failed to run {name}{RESET}")
150 | ok = False
151 | break
152 | end = datetime.now()
153 | total += end - start
154 | runs += 1
155 |
156 | average = total / runs
157 | if (
158 | i < args.runs - 1
159 | and args.timeout > 0
160 | and (total + average).total_seconds() > args.timeout
161 | ):
162 | print(f", timeout after {runs} run(s)", end="", flush=True)
163 | break
164 | if not ok:
165 | continue
166 | results.append((path.name, version_output, total / runs))
167 |
168 | print()
169 |
170 | if not results:
171 | print("No results")
172 | sys.exit()
173 |
174 | print("===")
175 |
176 | name_width = max(len(result[0]) for result in results)
177 | results.sort(key=itemgetter(2))
178 | for name, version, time in results:
179 | trimmed = str(time).split(":", 1)[1]
180 | print(f"{name:{name_width}} | {trimmed} {DIM}| {version}{RESET}")
181 |
--------------------------------------------------------------------------------
/uxntal/uxnmin.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | static unsigned int console_vector;
4 | static unsigned char ram[0x10000], dev[0x100], ptr[2], stk[2][0x100];
5 |
6 | static void
7 | system_print(char *name, int r)
8 | {
9 | unsigned char i;
10 | fprintf(stderr, "%s ", name);
11 | for(i = ptr[r] - 8; i != ptr[r]; i++)
12 | fprintf(stderr, "%02x%c", stk[r][i], i == 0xff ? '|' : ' ');
13 | fprintf(stderr, "<%02x\n", ptr[r]);
14 | }
15 |
16 | static unsigned char
17 | emu_dei(const unsigned char port)
18 | {
19 | return dev[port];
20 | }
21 |
22 | static void
23 | emu_deo(const unsigned char port, const unsigned char value)
24 | {
25 | dev[port] = value;
26 | switch(port) {
27 | case 0x0e: system_print("WST", 0), system_print("RST", 1); break;
28 | case 0x11: console_vector = dev[0x10] << 8 | value; return;
29 | case 0x18: fputc(value, stdout); return;
30 | case 0x19: fputc(value, stderr); return;
31 | }
32 | }
33 |
34 | #define REM ptr[_r] -= 1 + _2;
35 | #define DEC(m) stk[m][--ptr[m]]
36 | #define INC(m) stk[m][ptr[m]++]
37 | #define IMM(r) { r = ram[pc++] << 8, r |= ram[pc++]; }
38 | #define MOV(x) { if(_2) pc = x; else pc += (signed char)x; }
39 | #define PO1(o) o = DEC(_r);
40 | #define PO2(o) { PO1(o) o |= DEC(_r) << 8; }
41 | #define POx(o) if(_2) PO2(o) else PO1(o)
42 | #define GOT(o) if(_2) PO1(o[1]) PO1(o[0])
43 | #define DEO(o,r) emu_deo(o, r[0]); if(_2) emu_deo(o + 1, r[1]);
44 | #define POK(o,r,m) ram[o] = r[0]; if(_2) ram[(o + 1) & m] = r[1];
45 | #define RP1(i) INC(!_r) = i;
46 | #define PU1(i) INC(_r) = i;
47 | #define PUx(i) if(_2) { c = (i); PU1(c >> 8) PU1(c) } else PU1(i)
48 | #define PUT(i) PU1(i[0]) if(_2) PU1(i[1])
49 | #define DEI(i,r) r[0] = emu_dei(i); if(_2) r[1] = emu_dei(i + 1); PUT(r)
50 | #define PEK(i,r,m) r[0] = ram[i]; if(_2) r[1] = ram[(i + 1) & m]; PUT(r)
51 |
52 | #define OPC(opc, A, B) {\
53 | case 0x00|opc: {const int _2=0,_r=0;A B} goto step;\
54 | case 0x20|opc: {const int _2=1,_r=0;A B} goto step;\
55 | case 0x40|opc: {const int _2=0,_r=1;A B} goto step;\
56 | case 0x60|opc: {const int _2=1,_r=1;A B} goto step;\
57 | case 0x80|opc: {const int _2=0,_r=0;int k=ptr[0];A ptr[0]=k;B} goto step;\
58 | case 0xa0|opc: {const int _2=1,_r=0;int k=ptr[0];A ptr[0]=k;B} goto step;\
59 | case 0xc0|opc: {const int _2=0,_r=1;int k=ptr[1];A ptr[1]=k;B} goto step;\
60 | case 0xe0|opc: {const int _2=1,_r=1;int k=ptr[1];A ptr[1]=k;B} goto step; }
61 |
62 | static unsigned int
63 | uxn_eval(unsigned short pc)
64 | {
65 | unsigned int a, b, c, x[2], y[2], z[2];
66 | step:
67 | switch(ram[pc++]) {
68 | /* BRK */ case 0x00: return 1;
69 | /* JCI */ case 0x20: if(DEC(0)) { IMM(c) pc += c; } else pc += 2; goto step;
70 | /* JMI */ case 0x40: IMM(c) pc += c; goto step;
71 | /* JSI */ case 0x60: IMM(c) INC(1) = pc >> 8, INC(1) = pc, pc += c; goto step;
72 | /* LI2 */ case 0xa0: INC(0) = ram[pc++]; /* fall-through */
73 | /* LIT */ case 0x80: INC(0) = ram[pc++]; goto step;
74 | /* L2r */ case 0xe0: INC(1) = ram[pc++]; /* fall-through */
75 | /* LIr */ case 0xc0: INC(1) = ram[pc++]; goto step;
76 | /* INC */ OPC(0x01,POx(a),PUx(a + 1))
77 | /* POP */ OPC(0x02,REM,{})
78 | /* NIP */ OPC(0x03,GOT(x) REM,PUT(x))
79 | /* SWP */ OPC(0x04,GOT(x) GOT(y),PUT(x) PUT(y))
80 | /* ROT */ OPC(0x05,GOT(x) GOT(y) GOT(z),PUT(y) PUT(x) PUT(z))
81 | /* DUP */ OPC(0x06,GOT(x),PUT(x) PUT(x))
82 | /* OVR */ OPC(0x07,GOT(x) GOT(y),PUT(y) PUT(x) PUT(y))
83 | /* EQU */ OPC(0x08,POx(a) POx(b),PU1(b == a))
84 | /* NEQ */ OPC(0x09,POx(a) POx(b),PU1(b != a))
85 | /* GTH */ OPC(0x0a,POx(a) POx(b),PU1(b > a))
86 | /* LTH */ OPC(0x0b,POx(a) POx(b),PU1(b < a))
87 | /* JMP */ OPC(0x0c,POx(a),MOV(a))
88 | /* JCN */ OPC(0x0d,POx(a) PO1(b),if(b) MOV(a))
89 | /* JSR */ OPC(0x0e,POx(a),RP1(pc >> 8) RP1(pc) MOV(a))
90 | /* STH */ OPC(0x0f,GOT(x),RP1(x[0]) if(_2) RP1(x[1]))
91 | /* LDZ */ OPC(0x10,PO1(a),PEK(a, x, 0xff))
92 | /* STZ */ OPC(0x11,PO1(a) GOT(y),POK(a, y, 0xff))
93 | /* LDR */ OPC(0x12,PO1(a),PEK(pc + (signed char)a, x, 0xffff))
94 | /* STR */ OPC(0x13,PO1(a) GOT(y),POK(pc + (signed char)a, y, 0xffff))
95 | /* LDA */ OPC(0x14,PO2(a),PEK(a, x, 0xffff))
96 | /* STA */ OPC(0x15,PO2(a) GOT(y),POK(a, y, 0xffff))
97 | /* DEI */ OPC(0x16,PO1(a),DEI(a, x))
98 | /* DEO */ OPC(0x17,PO1(a) GOT(y),DEO(a, y))
99 | /* ADD */ OPC(0x18,POx(a) POx(b),PUx(b + a))
100 | /* SUB */ OPC(0x19,POx(a) POx(b),PUx(b - a))
101 | /* MUL */ OPC(0x1a,POx(a) POx(b),PUx(b * a))
102 | /* DIV */ OPC(0x1b,POx(a) POx(b),PUx(a ? b / a : 0))
103 | /* AND */ OPC(0x1c,POx(a) POx(b),PUx(b & a))
104 | /* ORA */ OPC(0x1d,POx(a) POx(b),PUx(b | a))
105 | /* EOR */ OPC(0x1e,POx(a) POx(b),PUx(b ^ a))
106 | /* SFT */ OPC(0x1f,PO1(a) POx(b),PUx(b >> (a & 0xf) << (a >> 4)))
107 | }
108 | return 0;
109 | }
110 |
111 | static void
112 | console_input(int c, unsigned int type)
113 | {
114 | dev[0x12] = c, dev[0x17] = type;
115 | if(console_vector && !dev[0x0f])
116 | uxn_eval(console_vector);
117 | }
118 |
119 | int
120 | main(int argc, char **argv)
121 | {
122 | FILE *f;
123 | if(argc < 2)
124 | return fprintf(stdout, "usage: %s file.rom [args..]\n", argv[0]);
125 | else if(!(f = fopen(argv[1], "rb")))
126 | return fprintf(stderr, "%s: %s not found.\n", argv[0], argv[1]);
127 | fread(&ram[0x100], 0xff00, 1, f), fclose(f);
128 | dev[0x17] = argc > 2;
129 | if(uxn_eval(0x100) && console_vector) {
130 | int i = 2;
131 | for(; i < argc; i++) {
132 | char c, *p = argv[i];
133 | while(!dev[0x0f] && (c = *p++))
134 | console_input(c, 2);
135 | console_input(0, 3 + (i == argc - 1));
136 | }
137 | while(!dev[0x0f]) {
138 | char c = fgetc(stdin);
139 | if(feof(stdin)) break;
140 | console_input(c, 1);
141 | }
142 | console_input(0, 4);
143 | }
144 | return dev[0x0f] & 0x7f;
145 | }
146 |
--------------------------------------------------------------------------------
/lbforth/lbForth.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * A minimal Forth compiler in C
4 | * By Leif Bruder http://defineanswer42.wordpress.com
5 | * Release 2014-04-04
6 | *
7 | * Based on Richard W.M. Jones' excellent Jonesforth sources/tutorial
8 | *
9 | * PUBLIC DOMAIN
10 | *
11 | * I, the copyright holder of this work, hereby release it into the public
12 | * domain. This applies worldwide. In case this is not legally possible, I grant
13 | * any entity the right to use this work for any purpose, without any conditions,
14 | * unless such conditions are required by law.
15 | *
16 | *******************************************************************************/
17 |
18 | /* Only a single include here; I'll define everything on the fly to keep
19 | * dependencies as low as possible. In this file, the only C standard functions
20 | * used are getchar, putchar and the EOF value. */
21 | #include
22 |
23 | /* Base cell data types. Use short/long on most systems for 16 bit cells. */
24 | /* Experiment here if necessary. */
25 | #define CELL_BASE_TYPE int
26 | #define DOUBLE_CELL_BASE_TYPE long
27 |
28 | /* Basic memory configuration */
29 | #define MEM_SIZE 65536 /* main memory size in bytes */
30 | #define STACK_SIZE 192 /* cells reserved for the stack */
31 | #define RSTACK_SIZE 100 /* cells reserved for the return stack */
32 | #define INPUT_LINE_SIZE 32 /* bytes reserved for the WORD buffer */
33 |
34 | /******************************************************************************/
35 |
36 | /* Our basic data types */
37 | typedef CELL_BASE_TYPE scell;
38 | typedef DOUBLE_CELL_BASE_TYPE dscell;
39 | typedef unsigned CELL_BASE_TYPE cell;
40 | typedef unsigned DOUBLE_CELL_BASE_TYPE dcell;
41 | typedef unsigned char byte;
42 | #define CELL_SIZE sizeof(cell)
43 | #define DCELL_SIZE sizeof(dcell)
44 |
45 | /* A few constants that describe the memory layout of this implementation */
46 | #define LATEST_POSITION INPUT_LINE_SIZE
47 | #define HERE_POSITION (LATEST_POSITION + CELL_SIZE)
48 | #define BASE_POSITION (HERE_POSITION + CELL_SIZE)
49 | #define STATE_POSITION (BASE_POSITION + CELL_SIZE)
50 | #define STACK_POSITION (STATE_POSITION + CELL_SIZE)
51 | #define RSTACK_POSITION (STACK_POSITION + STACK_SIZE * CELL_SIZE)
52 | #define HERE_START (RSTACK_POSITION + RSTACK_SIZE * CELL_SIZE)
53 | #define MAX_BUILTIN_ID 71
54 |
55 | /* Flags and masks for the dictionary */
56 | #define FLAG_IMMEDIATE 0x80
57 | #define FLAG_HIDDEN 0x40
58 | #define MASK_NAMELENGTH 0x1F
59 |
60 | /* This is the main memory to be used by this Forth. There will be no malloc
61 | * in this file. */
62 | byte memory[MEM_SIZE];
63 |
64 | /* Pointers to Forth variables stored inside the main memory array */
65 | cell *latest;
66 | cell *here;
67 | cell *base;
68 | cell *state;
69 | cell *sp;
70 | cell *stack;
71 | cell *rsp;
72 | cell *rstack;
73 |
74 | /* A few helper variables for the compiler */
75 | int exitReq;
76 | int errorFlag;
77 | cell next;
78 | cell lastIp;
79 | cell quit_address;
80 | cell commandAddress;
81 | cell maxBuiltinAddress;
82 |
83 | /* The TIB, stored outside the main memory array for now */
84 | char lineBuffer[128];
85 | int charsInLineBuffer = 0;
86 | int positionInLineBuffer = 0;
87 |
88 | /* A basic setup for defining builtins. This Forth uses impossibly low
89 | * adresses as IDs for the builtins so we can define builtins as
90 | * standard C functions. Slower but easier to port. */
91 | #define BUILTIN(id, name, c_name, flags) const int c_name##_id=id; const char* c_name##_name=name; const byte c_name##_flags=flags; void c_name()
92 | #define ADD_BUILTIN(c_name) addBuiltin(c_name##_id, c_name##_name, c_name##_flags, c_name)
93 | typedef void(*builtin)();
94 | builtin builtins[MAX_BUILTIN_ID] = { 0 };
95 |
96 | /* This is our initialization script containing all the words we define in
97 | * Forth for convenience. Focus is on simplicity, not speed. Partly copied from
98 | * Jonesforth (see top of file). */
99 | char *initscript_pos;
100 | const char *initScript =
101 | ": DECIMAL 10 BASE ! ;\n"
102 | ": HEX 16 BASE ! ;\n"
103 | ": OCTAL 8 BASE ! ;\n"
104 | ": 2DUP OVER OVER ;\n"
105 | ": 2DROP DROP DROP ;\n"
106 | ": NIP SWAP DROP ;\n"
107 | ": 2NIP 2SWAP 2DROP ;\n"
108 | ": TUCK SWAP OVER ;\n"
109 | ": / /MOD NIP ;\n"
110 | ": MOD /MOD DROP ;\n"
111 | ": BL 32 ;\n"
112 | ": CR 10 EMIT ;\n"
113 | ": SPACE BL EMIT ;\n"
114 | ": NEGATE 0 SWAP - ;\n"
115 | ": DNEGATE 0. 2SWAP D- ;\n"
116 | ": CELLS CELL * ;\n"
117 | ": ALLOT HERE @ + HERE ! ;\n"
118 | ": TRUE -1 ;\n"
119 | ": FALSE 0 ;\n"
120 | ": 0= 0 = ;\n"
121 | ": 0< 0 < ;\n"
122 | ": 0> 0 > ;\n"
123 | ": <> = 0= ;\n"
124 | ": <= > 0= ;\n"
125 | ": >= < 0= ;\n"
126 | ": 0<= 0 <= ;\n"
127 | ": 0>= 0 >= ;\n"
128 | ": 1+ 1 + ;\n"
129 | ": 1- 1 - ;\n"
130 | ": 2+ 2 + ;\n"
131 | ": 2- 2 - ;\n"
132 | ": 2/ 2 / ;\n"
133 | ": 2* 2 * ;\n"
134 | ": D2/ 2. D/ ;\n"
135 | ": +! DUP @ ROT + SWAP ! ;\n"
136 | ": [COMPILE] WORD FIND >CFA , ; IMMEDIATE\n"
137 | ": [CHAR] key ' LIT , , ; IMMEDIATE\n"
138 | ": RECURSE LATEST @ >CFA , ; IMMEDIATE\n"
139 | ": DOCOL 0 ;\n"
140 | ": CONSTANT CREATE DOCOL , ' LIT , , ' EXIT , ;\n"
141 | ": 2CONSTANT SWAP CREATE DOCOL , ' LIT , , ' LIT , , ' EXIT , ;\n"
142 | ": VARIABLE HERE @ CELL ALLOT CREATE DOCOL , ' LIT , , ' EXIT , ;\n" /* TODO: Allot AFTER the code, not before */
143 | ": 2VARIABLE HERE @ 2 CELLS ALLOT CREATE DOCOL , ' LIT , , ' EXIT , ;\n" /* TODO: Allot AFTER the code, not before */
144 | ": IF ' 0BRANCH , HERE @ 0 , ; IMMEDIATE\n"
145 | ": THEN DUP HERE @ SWAP - SWAP ! ; IMMEDIATE\n"
146 | ": ELSE ' BRANCH , HERE @ 0 , SWAP DUP HERE @ SWAP - SWAP ! ; IMMEDIATE\n"
147 | ": BEGIN HERE @ ; IMMEDIATE\n"
148 | ": UNTIL ' 0BRANCH , HERE @ - , ; IMMEDIATE\n"
149 | ": AGAIN ' BRANCH , HERE @ - , ; IMMEDIATE\n"
150 | ": WHILE ' 0BRANCH , HERE @ 0 , ; IMMEDIATE\n"
151 | ": REPEAT ' BRANCH , SWAP HERE @ - , DUP HERE @ SWAP - SWAP ! ; IMMEDIATE\n"
152 | ": UNLESS ' 0= , [COMPILE] IF ; IMMEDIATE\n"
153 | ": DO HERE @ ' SWAP , ' >R , ' >R , ; IMMEDIATE\n"
154 | ": LOOP ' R> , ' R> , ' SWAP , ' 1+ , ' 2DUP , ' = , ' 0BRANCH , HERE @ - , ' 2DROP , ; IMMEDIATE\n"
155 | ": +LOOP ' R> , ' R> , ' SWAP , ' ROT , ' + , ' 2DUP , ' <= , ' 0BRANCH , HERE @ - , ' 2DROP , ; IMMEDIATE\n"
156 | ": I ' R@ , ; IMMEDIATE\n"
157 | ": SPACES DUP 0> IF 0 DO SPACE LOOP ELSE DROP THEN ;\n"
158 | ": ABS DUP 0< IF NEGATE THEN ;\n"
159 | ": DABS 2DUP 0. D< IF DNEGATE THEN ;\n"
160 | ": .DIGIT DUP 9 > IF 55 ELSE 48 THEN + EMIT ;\n"
161 | ": .SIGN DUP 0< IF 45 EMIT NEGATE THEN ;\n" /* BUG: 10000000000... will be shown wrong */
162 | ": .POS BASE @ /MOD ?DUP IF RECURSE THEN .DIGIT ;\n"
163 | ": . .SIGN DUP IF .POS ELSE .DIGIT THEN ;\n"
164 | ": COUNTPOS SWAP 1 + SWAP BASE @ / ?DUP IF RECURSE THEN ;\n"
165 | ": DIGITS DUP 0< IF 1 ELSE 0 THEN SWAP COUNTPOS ;\n"
166 | ": .R OVER DIGITS - SPACES . ;\n"
167 | ": . . SPACE ;\n"
168 | ": ? @ . ;\n"
169 | ": .S DSP@ BEGIN DUP S0@ > WHILE DUP ? CELL - REPEAT DROP ;\n"
170 | ": TYPE 0 DO DUP C@ EMIT 1 + LOOP DROP ;\n"
171 | ": ALIGN BEGIN HERE @ CELL MOD WHILE 0 C, REPEAT ;\n"
172 | ": s\" ' LITSTRING , HERE @ 0 , BEGIN KEY DUP 34 <> WHILE C, REPEAT DROP DUP HERE @ SWAP - CELL - SWAP ! ALIGN ; IMMEDIATE\n"
173 | ": .\" [COMPILE] s\" ' TYPE , ; IMMEDIATE\n"
174 | ": ( BEGIN KEY [CHAR] ) = UNTIL ; IMMEDIATE\n"
175 | ": COUNT DUP 1+ SWAP C@ ;\n"
176 | ": MIN 2DUP < IF DROP ELSE NIP THEN ;\n"
177 | ": MAX 2DUP > IF DROP ELSE NIP THEN ;\n"
178 | ": D0= OR 0= ;\n"
179 | ": DMIN 2OVER 2OVER D< IF 2DROP ELSE 2NIP THEN ;\n"
180 | ": DMAX 2OVER 2OVER D> IF 2DROP ELSE 2NIP THEN ;\n"
181 | ;
182 |
183 | /******************************************************************************/
184 |
185 | /* The primary data output function. This is the place to change if you want
186 | * to e.g. output data on a microcontroller via a serial interface. */
187 | void putkey(char c)
188 | {
189 | putchar(c);
190 | }
191 |
192 | /* The primary data input function. This is where you place the code to e.g.
193 | * read from a serial line. */
194 | int llkey()
195 | {
196 | if (*initscript_pos) return *(initscript_pos++);
197 | return getchar();
198 | }
199 |
200 | /* Anything waiting in the keyboard buffer? */
201 | int keyWaiting()
202 | {
203 | return positionInLineBuffer < charsInLineBuffer ? -1 : 0;
204 | }
205 |
206 | /* Line buffered character input. We're duplicating the functionality of the
207 | * stdio library here to make the code easier to port to other input sources */
208 | int getkey()
209 | {
210 | int c;
211 |
212 | if (keyWaiting())
213 | return lineBuffer[positionInLineBuffer++];
214 |
215 | charsInLineBuffer = 0;
216 | while ((c = llkey()) != EOF)
217 | {
218 | if (charsInLineBuffer == sizeof(lineBuffer)) break;
219 | lineBuffer[charsInLineBuffer++] = c;
220 | if (c == '\n') break;
221 | }
222 |
223 | positionInLineBuffer = 1;
224 | return lineBuffer[0];
225 | }
226 |
227 | /* C string output */
228 | void tell(const char *str)
229 | {
230 | while (*str)
231 | putkey(*str++);
232 | }
233 |
234 | /* The basic (data) stack operations */
235 |
236 | cell pop()
237 | {
238 | if (*sp == 1)
239 | {
240 | tell("? Stack underflow\n");
241 | errorFlag = 1;
242 | return 0;
243 | }
244 | return stack[--(*sp)];
245 | }
246 |
247 | cell tos()
248 | {
249 | if (*sp == 1)
250 | {
251 | tell("? Stack underflow\n");
252 | errorFlag = 1;
253 | return 0;
254 | }
255 | return stack[(*sp)-1];
256 | }
257 |
258 | void push(cell data)
259 | {
260 | if (*sp >= STACK_SIZE)
261 | {
262 | tell("? Stack overflow\n");
263 | errorFlag = 1;
264 | return;
265 | }
266 | stack[(*sp)++] = data;
267 | }
268 |
269 | dcell dpop()
270 | {
271 | cell tmp[2];
272 | tmp[1] = pop();
273 | tmp[0] = pop();
274 | return *((dcell*)tmp);
275 | }
276 |
277 | void dpush(dcell data)
278 | {
279 | cell tmp[2];
280 | *((dcell*)tmp) = data;
281 | push(tmp[0]);
282 | push(tmp[1]);
283 | }
284 |
285 | /* The basic return stack operations */
286 |
287 | cell rpop()
288 | {
289 | if (*rsp == 1)
290 | {
291 | tell("? RStack underflow\n");
292 | errorFlag = 1;
293 | return 0;
294 | }
295 | return rstack[--(*rsp)];
296 | }
297 |
298 | void rpush(cell data)
299 | {
300 | if (*rsp >= RSTACK_SIZE)
301 | {
302 | tell("? RStack overflow\n");
303 | errorFlag = 1;
304 | return;
305 | }
306 | rstack[(*rsp)++] = data;
307 | }
308 |
309 | /* Secure memory access */
310 |
311 | cell readMem(cell address)
312 | {
313 | if (address > MEM_SIZE)
314 | {
315 | tell("Internal error in readMem: Invalid addres\n");
316 | errorFlag = 1;
317 | return 0;
318 | }
319 | return *((cell*)(memory + address));
320 | }
321 |
322 | void writeMem(cell address, cell value)
323 | {
324 | if (address > MEM_SIZE)
325 | {
326 | tell("Internal error in writeMem: Invalid address\n");
327 | errorFlag = 1;
328 | return;
329 | }
330 | *((cell*)(memory + address)) = value;
331 | }
332 |
333 | /* Reading a word into the input line buffer */
334 | byte readWord()
335 | {
336 | char *line = (char*)memory;
337 | byte len = 0;
338 | int c;
339 |
340 | while ((c = getkey()) != EOF)
341 | {
342 | if (c == ' ') continue;
343 | if (c == '\n') continue;
344 | if (c != '\\') break;
345 |
346 | while ((c = getkey()) != EOF)
347 | if (c == '\n')
348 | break;
349 | }
350 |
351 | while (c != ' ' && c != '\n' && c != EOF)
352 | {
353 | if (len >= (INPUT_LINE_SIZE - 1))
354 | break;
355 | line[++len] = c;
356 | c = getkey();
357 | }
358 | line[0] = len;
359 | return len;
360 | }
361 |
362 | /* toupper() clone so we don't have to pull in ctype.h */
363 | char up(char c)
364 | {
365 | return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
366 | }
367 |
368 | /* Dictionary lookup */
369 | cell findWord(cell address, cell len)
370 | {
371 | cell ret = *latest;
372 | char *name = (char*)&memory[address];
373 | cell i;
374 | int found;
375 |
376 | for (ret = *latest; ret; ret = readMem(ret))
377 | {
378 | if ((memory[ret + CELL_SIZE] & MASK_NAMELENGTH) != len) continue;
379 | if (memory[ret + CELL_SIZE] & FLAG_HIDDEN) continue;
380 |
381 | found = 1;
382 | for (i = 0; i < len; i++)
383 | {
384 | if (up(memory[ret + i + 1 + CELL_SIZE]) != up(name[i]))
385 | {
386 | found = 0;
387 | break;
388 | }
389 | }
390 | if (found) break;
391 | }
392 | return ret;
393 | }
394 |
395 | /* Basic number parsing, base <= 36 only atm */
396 | void parseNumber(byte *word, cell len, dcell *number, cell *notRead, byte *isDouble)
397 | {
398 | int negative = 0;
399 | cell i;
400 | char c;
401 | cell current;
402 |
403 | *number = 0;
404 | *isDouble = 0;
405 |
406 | if (len == 0)
407 | {
408 | *notRead = 0;
409 | return;
410 | }
411 |
412 | if (word[0] == '-')
413 | {
414 | negative = 1;
415 | len--;
416 | word++;
417 | }
418 | else if (word[0] == '+')
419 | {
420 | len--;
421 | word++;
422 | }
423 |
424 | for (i = 0; i < len; i++)
425 | {
426 | c = *word;
427 | word++;
428 | if (c == '.') { *isDouble = 1; continue; }
429 | else if (c >= '0' && c <= '9') current = c - '0';
430 | else if (c >= 'A' && c <= 'Z') current = 10 + c - 'A';
431 | else if (c >= 'a' && c <= 'z') current = 10 + c - 'a';
432 | else break;
433 |
434 | if (current >= *base) break;
435 |
436 | *number = *number * *base + current;
437 | }
438 |
439 | *notRead = len - i;
440 | if (negative) *number = (-((scell)*number));
441 | }
442 |
443 | /*******************************************************************************
444 | *
445 | * Builtin definitions
446 | *
447 | *******************************************************************************/
448 |
449 | BUILTIN(0, "RUNDOCOL", docol, 0)
450 | {
451 | rpush(lastIp);
452 | next = commandAddress + CELL_SIZE;
453 | }
454 |
455 | /* The first few builtins are very simple, not need to waste vertical space here */
456 | BUILTIN( 1, "CELL", doCellSize, 0) { push(CELL_SIZE); }
457 | BUILTIN( 2, "@", memRead, 0) { push(readMem(pop())); }
458 | BUILTIN( 3, "C@", memReadByte, 0) { push(memory[pop()]); }
459 | BUILTIN( 4, "KEY", key, 0) { push(getkey()); }
460 | BUILTIN( 5, "EMIT", emit, 0) { putkey(pop() & 255); }
461 | BUILTIN( 6, "DROP", drop, 0) { pop(); }
462 | BUILTIN( 7, "EXIT", doExit, 0) { next = rpop(); }
463 | BUILTIN( 8, "BYE", bye, 0) { exitReq = 1; }
464 | BUILTIN( 9, "LATEST", doLatest, 0) { push(LATEST_POSITION); }
465 | BUILTIN(10, "HERE", doHere, 0) { push(HERE_POSITION); }
466 | BUILTIN(11, "BASE", doBase, 0) { push(BASE_POSITION); }
467 | BUILTIN(12, "STATE", doState, 0) { push(STATE_POSITION); }
468 | BUILTIN(13, "[", gotoInterpreter, FLAG_IMMEDIATE) { *state = 0; }
469 | BUILTIN(14, "]", gotoCompiler, 0) { *state = 1; }
470 | BUILTIN(15, "HIDE", hide, 0) { memory[*latest + CELL_SIZE] ^= FLAG_HIDDEN; }
471 | BUILTIN(16, "R>", rtos, 0) { push(rpop()); }
472 | BUILTIN(17, ">R", stor, 0) { rpush(pop()); }
473 | BUILTIN(18, "KEY?", key_p, 0) { push(keyWaiting()); }
474 | BUILTIN(19, "BRANCH", branch, 0) { next += readMem(next); }
475 | BUILTIN(20, "0BRANCH", zbranch, 0) { next += pop() ? CELL_SIZE : readMem(next); }
476 | BUILTIN(21, "IMMEDIATE", toggleImmediate, FLAG_IMMEDIATE) { memory[*latest + CELL_SIZE] ^= FLAG_IMMEDIATE; }
477 | BUILTIN(22, "FREE", doFree, 0) { push(MEM_SIZE - *here); }
478 | BUILTIN(23, "S0@", s0_r, 0) { push(STACK_POSITION + CELL_SIZE); }
479 | BUILTIN(24, "DSP@", dsp_r, 0) { push(STACK_POSITION + *sp * CELL_SIZE); }
480 | BUILTIN(25, "NOT", not, 0) { push(~pop()); }
481 | BUILTIN(26, "DUP", dup, 0) { push(tos()); }
482 |
483 | BUILTIN(27, "!", memWrite, 0)
484 | {
485 | cell address = pop();
486 | cell value = pop();
487 | writeMem(address, value);
488 | }
489 |
490 | BUILTIN(28, "C!", memWriteByte, 0)
491 | {
492 | cell address = pop();
493 | cell value = pop();
494 | memory[address] = value & 255;
495 | }
496 |
497 | BUILTIN(29, "SWAP", swap, 0)
498 | {
499 | cell a = pop();
500 | cell b = pop();
501 | push(a);
502 | push(b);
503 | }
504 |
505 | BUILTIN(30, "OVER", over, 0)
506 | {
507 | cell a = pop();
508 | cell b = tos();
509 | push(a);
510 | push(b);
511 | }
512 |
513 | BUILTIN(31, ",", comma, 0)
514 | {
515 | push(*here);
516 | memWrite();
517 | *here += CELL_SIZE;
518 | }
519 |
520 | BUILTIN(32, "C,", commaByte, 0)
521 | {
522 | push(*here);
523 | memWriteByte();
524 | *here += sizeof(byte);
525 | }
526 |
527 | BUILTIN(33, "WORD", word, 0)
528 | {
529 | byte len = readWord();
530 | push(1);
531 | push(len);
532 | }
533 |
534 | BUILTIN(34, "FIND", find, 0)
535 | {
536 | cell len = pop();
537 | cell address = pop();
538 | cell ret = findWord(address, len);
539 | push(ret);
540 | }
541 |
542 | cell getCfa(cell address)
543 | {
544 | byte len = (memory[address + CELL_SIZE] & MASK_NAMELENGTH) + 1;
545 | while ((len & (CELL_SIZE-1)) != 0) len++;
546 | return address + CELL_SIZE + len;
547 | }
548 |
549 | BUILTIN(35, ">CFA", cfa, 0)
550 | {
551 | cell address = pop();
552 | cell ret = getCfa(address);
553 | if (ret < maxBuiltinAddress)
554 | push(readMem(ret));
555 | else
556 | push(ret);
557 | }
558 |
559 | BUILTIN(36, "NUMBER", number, 0)
560 | {
561 | dcell num;
562 | cell notRead;
563 | byte isDouble;
564 | cell len = pop();
565 | byte* address = &memory[pop()];
566 | parseNumber(address, len, &num, ¬Read, &isDouble);
567 | if (isDouble) dpush(num); else push((cell)num);
568 | push(notRead);
569 | }
570 |
571 | BUILTIN(37, "LIT", lit, 0)
572 | {
573 | push(readMem(next));
574 | next += CELL_SIZE;
575 | }
576 |
577 | /* Outer and inner interpreter, TODO split up */
578 | BUILTIN(38, "QUIT", quit, 0)
579 | {
580 | cell address;
581 | dcell number;
582 | cell notRead;
583 | cell command;
584 | int i;
585 | byte isDouble;
586 | cell tmp[2];
587 |
588 | int immediate;
589 |
590 | for (exitReq = 0; exitReq == 0;)
591 | {
592 | lastIp = next = quit_address;
593 | errorFlag = 0;
594 |
595 | word();
596 | find();
597 |
598 | address = pop();
599 | if (address)
600 | {
601 | immediate = (memory[address + CELL_SIZE] & FLAG_IMMEDIATE);
602 | commandAddress = getCfa(address);
603 | command = readMem(commandAddress);
604 | if (*state && !immediate)
605 | {
606 | if (command < MAX_BUILTIN_ID && command != docol_id)
607 | push(command);
608 | else
609 | push(commandAddress);
610 | comma();
611 | }
612 | else
613 | {
614 | while (!errorFlag && !exitReq)
615 | {
616 | if (command == quit_id) break;
617 | else if (command < MAX_BUILTIN_ID) builtins[command]();
618 | else
619 | {
620 | lastIp = next;
621 | next = command;
622 | }
623 |
624 | commandAddress = next;
625 | command = readMem(commandAddress);
626 | next += CELL_SIZE;
627 | }
628 | }
629 | }
630 | else
631 | {
632 | parseNumber(&memory[1], memory[0], &number, ¬Read, &isDouble);
633 | if (notRead)
634 | {
635 | tell("Unknown word: ");
636 | for (i=0; i", larger, 0)
794 | {
795 | scell a1 = pop();
796 | scell a2 = pop();
797 | push(a2 > a1 ? -1 : 0);
798 | }
799 |
800 | BUILTIN(53, "AND", doAnd, 0)
801 | {
802 | cell a1 = pop();
803 | cell a2 = pop();
804 | push(a2 & a1);
805 | }
806 |
807 | BUILTIN(54, "OR", doOr, 0)
808 | {
809 | cell a1 = pop();
810 | cell a2 = pop();
811 | push(a2 | a1);
812 | }
813 |
814 | BUILTIN(55, "?DUP", p_dup, 0)
815 | {
816 | cell a = tos();
817 | if (a) push(a);
818 | }
819 |
820 | BUILTIN(56, "LITSTRING", litstring, 0)
821 | {
822 | cell length = readMem(next);
823 | next += CELL_SIZE;
824 | push(next);
825 | push(length);
826 | next += length;
827 | while (next & (CELL_SIZE-1))
828 | next++;
829 | }
830 |
831 | BUILTIN(57, "XOR", xor, 0)
832 | {
833 | cell a = pop();
834 | cell b = pop();
835 | push(a ^ b);
836 | }
837 |
838 | BUILTIN(58, "*/", timesDivide, 0)
839 | {
840 | cell n3 = pop();
841 | dcell n2 = pop();
842 | dcell n1 = pop();
843 | dcell r = (n1 * n2) / n3;
844 | push((cell)r);
845 | if ((cell)r != r)
846 | {
847 | tell("Arithmetic overflow\n");
848 | errorFlag = 1;
849 | }
850 | }
851 |
852 | BUILTIN(59, "*/MOD", timesDivideMod, 0)
853 | {
854 | cell n3 = pop();
855 | dcell n2 = pop();
856 | dcell n1 = pop();
857 | dcell r = (n1 * n2) / n3;
858 | dcell m = (n1 * n2) % n3;
859 | push((cell)m);
860 | push((cell)r);
861 | if ((cell)r != r)
862 | {
863 | tell("Arithmetic overflow\n");
864 | errorFlag = 1;
865 | }
866 | }
867 |
868 | BUILTIN(60, "D=", dequals, 0)
869 | {
870 | dcell a1 = dpop();
871 | dcell a2 = dpop();
872 | push(a2 == a1 ? -1 : 0);
873 | }
874 |
875 | BUILTIN(61, "D<", dsmaller, 0)
876 | {
877 | dscell a1 = dpop();
878 | dscell a2 = dpop();
879 | push(a2 < a1 ? -1 : 0);
880 | }
881 |
882 | BUILTIN(62, "D>", dlarger, 0)
883 | {
884 | dscell a1 = dpop();
885 | dscell a2 = dpop();
886 | push(a2 > a1 ? -1 : 0);
887 | }
888 |
889 | BUILTIN(63, "DU<", dusmaller, 0)
890 | {
891 | dcell a1 = dpop();
892 | dcell a2 = dpop();
893 | push(a2 < a1 ? -1 : 0);
894 | }
895 |
896 | BUILTIN(64, "D+", dplus, 0)
897 | {
898 | dscell n1 = dpop();
899 | dscell n2 = dpop();
900 | dpush(n1 + n2);
901 | }
902 |
903 | BUILTIN(65, "D-", dminus, 0)
904 | {
905 | dscell n1 = dpop();
906 | dscell n2 = dpop();
907 | dpush(n2 - n1);
908 | }
909 |
910 | BUILTIN(66, "D*", dmul, 0)
911 | {
912 | dscell n1 = dpop();
913 | dscell n2 = dpop();
914 | dpush(n1 * n2);
915 | }
916 |
917 | BUILTIN(67, "D/", ddiv, 0)
918 | {
919 | dscell n1 = dpop();
920 | dscell n2 = dpop();
921 | dpush(n2 / n1);
922 | }
923 |
924 | BUILTIN(68, "2SWAP", dswap, 0)
925 | {
926 | dcell a = dpop();
927 | dcell b = dpop();
928 | dpush(a);
929 | dpush(b);
930 | }
931 |
932 | BUILTIN(69, "2OVER", dover, 0)
933 | {
934 | dcell a = dpop();
935 | dcell b = dpop();
936 | dpush(b);
937 | dpush(a);
938 | dpush(b);
939 | }
940 |
941 | BUILTIN(70, "2ROT", drot, 0)
942 | {
943 | dcell a = dpop();
944 | dcell b = dpop();
945 | dcell c = dpop();
946 | dpush(b);
947 | dpush(a);
948 | dpush(c);
949 | }
950 |
951 | /*******************************************************************************
952 | *
953 | * Loose ends
954 | *
955 | *******************************************************************************/
956 |
957 | /* Create a word in the dictionary */
958 | void createWord(const char* name, byte len, byte flags)
959 | {
960 | cell newLatest = *here;
961 | push(*latest);
962 | comma();
963 | push(len | flags);
964 | commaByte();
965 | while (len--)
966 | {
967 | push(*name);
968 | commaByte();
969 | name++;
970 | }
971 | while (*here & (CELL_SIZE-1))
972 | {
973 | push(0);
974 | commaByte();
975 | }
976 | *latest = newLatest;
977 | }
978 |
979 | /* A simple strlen clone so we don't have to pull in string.h */
980 | byte slen(const char *str)
981 | {
982 | byte ret = 0;
983 | while (*str++) ret++;
984 | return ret;
985 | }
986 |
987 | /* Add a builtin to the dictionary */
988 | void addBuiltin(cell code, const char* name, const byte flags, builtin f)
989 | {
990 | if (errorFlag) return;
991 |
992 | if (code >= MAX_BUILTIN_ID)
993 | {
994 | tell("Error adding builtin ");
995 | tell(name);
996 | tell(": Out of builtin IDs\n");
997 | errorFlag = 1;
998 | return;
999 | }
1000 |
1001 | if (builtins[code] != 0)
1002 | {
1003 | tell("Error adding builtin ");
1004 | tell(name);
1005 | tell(": ID given twice\n");
1006 | errorFlag = 1;
1007 | return;
1008 | }
1009 |
1010 | builtins[code] = f;
1011 | createWord(name, slen(name), flags);
1012 | push(code);
1013 | comma();
1014 | push(doExit_id);
1015 | comma();
1016 | }
1017 |
1018 | /* Program setup and jump to outer interpreter */
1019 | int main()
1020 | {
1021 | errorFlag = 0;
1022 |
1023 | if (DCELL_SIZE != 2*CELL_SIZE)
1024 | {
1025 | tell("Configuration error: DCELL_SIZE != 2*CELL_SIZE\n");
1026 | return 1;
1027 | }
1028 |
1029 | state = (cell*)&memory[STATE_POSITION];
1030 | base = (cell*)&memory[BASE_POSITION];
1031 | latest = (cell*)&memory[LATEST_POSITION];
1032 | here = (cell*)&memory[HERE_POSITION];
1033 | sp = (cell*)&memory[STACK_POSITION];
1034 | stack = (cell*)&memory[STACK_POSITION + CELL_SIZE];
1035 | rsp = (cell*)&memory[RSTACK_POSITION];
1036 | rstack = (cell*)&memory[RSTACK_POSITION + CELL_SIZE];
1037 |
1038 | *sp = *rsp = 1;
1039 | *state = 0;
1040 | *base = 10;
1041 | *latest = 0;
1042 | *here = HERE_START;
1043 |
1044 | ADD_BUILTIN(docol);
1045 | ADD_BUILTIN(doCellSize);
1046 | ADD_BUILTIN(memRead);
1047 | ADD_BUILTIN(memWrite);
1048 | ADD_BUILTIN(memReadByte);
1049 | ADD_BUILTIN(memWriteByte);
1050 | ADD_BUILTIN(key);
1051 | ADD_BUILTIN(emit);
1052 | ADD_BUILTIN(swap);
1053 | ADD_BUILTIN(dup);
1054 | ADD_BUILTIN(drop);
1055 | ADD_BUILTIN(over);
1056 | ADD_BUILTIN(comma);
1057 | ADD_BUILTIN(commaByte);
1058 | ADD_BUILTIN(word);
1059 | ADD_BUILTIN(find);
1060 | ADD_BUILTIN(cfa);
1061 | ADD_BUILTIN(doExit);
1062 | ADD_BUILTIN(quit);
1063 | quit_address = getCfa(*latest);
1064 | ADD_BUILTIN(number);
1065 | ADD_BUILTIN(bye);
1066 | ADD_BUILTIN(doLatest);
1067 | ADD_BUILTIN(doHere);
1068 | ADD_BUILTIN(doBase);
1069 | ADD_BUILTIN(doState);
1070 | ADD_BUILTIN(plus);
1071 | ADD_BUILTIN(minus);
1072 | ADD_BUILTIN(mul);
1073 | ADD_BUILTIN(divmod);
1074 | ADD_BUILTIN(rot);
1075 | ADD_BUILTIN(gotoInterpreter);
1076 | ADD_BUILTIN(gotoCompiler);
1077 | ADD_BUILTIN(doCreate);
1078 | ADD_BUILTIN(hide);
1079 | ADD_BUILTIN(lit);
1080 | ADD_BUILTIN(colon);
1081 | ADD_BUILTIN(semicolon);
1082 | ADD_BUILTIN(rtos);
1083 | ADD_BUILTIN(stor);
1084 | ADD_BUILTIN(rget);
1085 | ADD_BUILTIN(doJ);
1086 | ADD_BUILTIN(tick);
1087 | ADD_BUILTIN(key_p);
1088 | ADD_BUILTIN(equals);
1089 | ADD_BUILTIN(smaller);
1090 | ADD_BUILTIN(larger);
1091 | ADD_BUILTIN(doAnd);
1092 | ADD_BUILTIN(doOr);
1093 | ADD_BUILTIN(branch);
1094 | ADD_BUILTIN(zbranch);
1095 | ADD_BUILTIN(toggleImmediate);
1096 | ADD_BUILTIN(doFree);
1097 | ADD_BUILTIN(p_dup);
1098 | ADD_BUILTIN(s0_r);
1099 | ADD_BUILTIN(dsp_r);
1100 | ADD_BUILTIN(litstring);
1101 | ADD_BUILTIN(not);
1102 | ADD_BUILTIN(xor);
1103 | ADD_BUILTIN(timesDivide);
1104 | ADD_BUILTIN(timesDivideMod);
1105 | ADD_BUILTIN(dequals);
1106 | ADD_BUILTIN(dsmaller);
1107 | ADD_BUILTIN(dlarger);
1108 | ADD_BUILTIN(dusmaller);
1109 | ADD_BUILTIN(dplus);
1110 | ADD_BUILTIN(dminus);
1111 | ADD_BUILTIN(dmul);
1112 | ADD_BUILTIN(ddiv);
1113 | ADD_BUILTIN(dswap);
1114 | ADD_BUILTIN(dover);
1115 | ADD_BUILTIN(drot);
1116 |
1117 | maxBuiltinAddress = (*here) - 1;
1118 |
1119 | if (errorFlag) return 1;
1120 |
1121 | initscript_pos = (char*)initScript;
1122 | quit();
1123 | return 0;
1124 | }
1125 |
--------------------------------------------------------------------------------